Tip:
Highlight text to annotate it
X
All right. Let's do the initial vote. The initial vote says red,
blue, orange, green in almost equal proportion. So this is
either a really good question or a really bad one. Let's find
out by having you guys talk about it for about a minute. Okay.
This is ... I think this is a good question because it asked you
to sort of push beyond sort of this ... all the specific things
that have been presented in the lecture. Let's do another vote
here, another vote on which method or methods ... there's been a
substantial movement towards blue and I'm not talking about the
congress, I'm talking about just the answers. Yes. Okay. Okay
let's ... so let's go through ... so what's the key to this
question? The key to this question is remembering that if we're
going to create a new review and associate it to a movie,
somewhere in its life before it gets created, we got to be able
to assign the movie ID field. All right. So we need on or more
way or ways of doing that, that at the time the review is
created that field is going to get assigned. So what about this
first choice? Review create, well, I'm just passing an explicit
value for the ID of the movie that I want to be owned, right? So
this is just like any other active record create operation. I
can just pass explicit values for every single attribute and
movie ID is just an attribute. It happened to be an attribute
that plays the special role in managing the association but you
can assign to it. So the first one would work. It's not terribly
idiomatic because you have choices like for example what happens
is I say reviews. build? Well, because build basically has a way
of reaching back to the owning object right? What is m. reviews?
m. reviews is an object able to do the query of which reviews
belong to this movie. Remember the query's real easy, so the
query doesn't happen right away, but it's an object that could
do that query which means the object must know the idea of
movie, otherwise there'd be no way for it to do the query. So
what build does is it give you ... it's like new, it gives you a
blank object you can fill in, except that the foreign key field
has already been filled in for you and it exist for exactly the
reason you'd think, it's to make it more idiomatic, right. So
that you don't have to do the first one where you're naming the
foreign key explicitly. What's so bad about naming the foreign
key explicitly? In many cases it's not the worst evil in the
world, but as I mentioned you might be working for example with
a legacy data base where the foreign key fields don't have nice
names like movie_ ID because they were built to work with some
other system and you might not have the option of renaming them,
so in those cases, the active record association module gives
you a bunch of options so that you can override how the fields
are named that manage the foreign keys and things like build
will still do the right thing, they'll still honor your weird
non- standard foreign key names. What about this one? So again,
what's the idea here? What is m. reviews? Well, it is an object
that knows what m's ideas, that's for darn sure and that means
that one could imagine redefining the less, less method which is
sort of a pen down to the end of an enumeration such that part
of what it does is as this review is created, right? review. new
with potatoes 5 has no foreign key in it, but one could
certainly imagine defining this instance method so that it
essentially fills in that foreign key on the way in and that's
actually just what happens. So when you use associations, this
is one of the other methods that gets over written so that when
you try to add or review on for an existing movie, the right
thing happens. It does more or less what you would expect,
right? And it does it by essentially using dynamic writing of
the methods, so all of these methods, blue would have been the
correct answer. All of these methods will actually do it. Most
people prefer to use the middle one because it separates the
building and saving it into two steps, you can control them a
little bit better, but the third one will work just as well and
I don't recommend the first one if you have any choice. So let's
talk about this, since I see there's some questions about it.
Male: So does the [ inaudible 00:03:41] sort of propagating the
same way that m. destroy, can destroy its [ inaudible 00:03:45].
So the question is in the same way that m. destroy can destroy
the owned objects which is something we actually haven't talking
about just yet, but we will, is it also the case that m. save
will sort of save the reviews associated with the movie?
It's ... that's a really good question and the interesting
answer is yes. And the reason I say it's an interesting answer
is because if you think about it for a moment, when I'm creating
a new review to be associated with an existing movie, what
changes occur to the row representing that movie and the movie's
stable? Hint, it's a trick. No changes right? The only changes
is in the new review, I've got to have a foreign key pointing
back to that movie. So it seems counter intuitive that it would
be calling save on the movie object if the movie object in the
database doesn't actually have to change. But in fact, what you
just asked is correct. What actually happens is that when you do
a save on an object that owns other objects, it triggers, saves
of all of the owned objects that had been changed or created,
right? And again, why is it that, even though the movie itself
is not changing, why does save work that way when you do it on
the movie? Because the whole ... the thing we're trying to get
with this obstruction is the illusion that the movie is the
owning object, so saving it feels like it ought to save all the
owned objects, right? It should sort of save its children. So
this is provided because it provides lesser price for the
programmer. And for the same reason here, here in this case,
what's the difference between the second and third example, in
the second example, I created a new review right? So the value
of R is a thing that is a review object and then I'm saving that
review object directly. In this case, the value of m is a movie,
but when I save it, all of the owned objects, including ones
that were saved or created or updated since I loaded it, they
also get saved as a side effect. And by the way, because I've
used the dangerous, the *** version of save, that means that if
anything goes wrong in saving the owned objects, it will fail as
well, right? So just like doing a save with a ***, we'll throw
an exception if the object is invalid. When I save ***, the
owning side of an association, if errors occur when saving the
owned side, those areas will cause exceptions as well. Really
good question. Was there... there was another ... yes? Male: So
before you say that [ inaudible 00:06:01] to some kind of movie
goers? How come that we don't see anything? In this example, I
was just focusing on the movies and reviews association. So yes,
this ... in this question I didn't want you to worry about the
movie goer association. However, had the question included a
constraint about making sure the review was also owned by a
movie goer, then we would have had ... and that's an interesting
case, right? Because we could say m. reviews. build, that will
fill in the foreign key for the review or we could have said
movie goers ... if we had a movie goer, let's say moviegoer.
reviews. build, that would fill in the foreign key for movie
goers. But we actually need both foreign keys. So in that case,
somewhere along the line, you would end up having to fill in one
of them explicitly yourself. And then when we talk about how you
do controller actions that manage objects and associations,
we'll see how you do that.