Updating children in a has_many relationship


#1

If a parent has_many children, The children can be set using
parent.children_ids = [] which is very cool. If the parent is a new
record, nothing will happen until the parent is saved. If the parent
is an existing record, the children will be immediately updated
regardless of whether the parent has been modified or validated. In
fact, the parent model will have no indication that the children have
been modified at all.

Am I the only one that thinks this is odd behavior? It seems like
there should be a more consistent approach.

Thanks,
Tom


#2

I don’t think it’s odd at all… the only reason it’s not saved until
the Parent is initially saved is if the parent has no ID, how cna you
assign parent_id to the child ( or the join table ).

If you’re modifying the children w/o touching the parent… say
categories and posts in those categories… It would be up to the
category model to validate any changes you make to it… and if you
changed a post in one of those categories… or changed the category
the post belonged to… why shouldn’t it be changed right away? Why
would I need to re-validate the category?


#3

Why shouldn’t it be changed right away? Because the parent may be
invalid.

Really, the problem is consistency. If are doing an update to the
parent and children and the parent is invalid, the children may or may
not be affected. The consistent way to handle it would be to not
update the children until the parent is saved. IMHO

Thanks,
Tom


#4

I disagree… that should be up to the developer to check… like my
example, why do I need to validate the category, each time I post?

My feeling is that if it’s something that you need to have, then
create a before_filter and have it validate, otherwise you’re
validating things that never change…

although I can see your argument for consistency… I still have no
problem with the way it is now…

That being said, my opinion rarely matter :stuck_out_tongue:


#5

Same thing though… saving a category doesn’t necessarily mean I
need to save every post… so you have to choose the option that is
less stressful… imagine a category with 10,000 posts… updating
the category would require you to save 10,000 posts…

same with any parent-child relationship…

I haven’t played with it in awhile, so I can comment specifically on
your example with calling category.post_ids = post.id auto saving it,
unless you’re calling it during a create call… to me that would
seem incorrect…

That being said, post.category_ids is the way it would need to be
done… because the posts are assigned the category… in this case
calling that SHOULD NOT save the post, and should require me to save
it manutally…

if I do post.create( params[:post] ) and one of the params is
category_ids[ 1,4,6] then on the create the post is saved… if I’m
in the middle of am action and go post.category_ids = 1,2,3 then it
SHOULD NOT save until I call post.save

I think I just confused myself.


#6

That isn’t exactly how it works. If you have a category with 10,000
posts, you would use the method “category.posts << post”. This has
the same inconsistency that if the category is an existing category,
the post is immediately saved. If the category is a new category, the
post will not be saved until either you call “category.save” or
“post.save”.

In a parent-child relationship, the parent will automatically save the
child if the child is added to the child collection. If the parent is
unsaved, it stays associated with the parent until the parent is
saved. Since you can’t always save the child, it would seem to be
more consistent to always wait to save the child until either the
parent or the child is explicitly saved. My two cents!

Thanks,
Tom


#7

Even in the case you mention, for adding a category to a post, I would
think you would use “past.category = category”, or the
“post.category_id = category.id” method – neither method would cause
the post to save until you called “post.save”.

However, if you were to call “category.post_ids = post.id”, it would
immediately save the post – now “post.save” is not required. Oh
wait! If the category was a NEW category it wouldn’t save the post
and now you would need to call “post.save”.

The inconsistent behavior makes it hard for me to use this very cool
method. Not a lot of people chiming in so sw0rdfish, I’m thinking my
opinion matters even less!

Thanks,
Tom


#8

yeah I see what you’re saying now…

I’ve run into it a few times where changes aren’t saved, and it turns
out to be as a result of what you mention…

Fair enough argument… you should bring it up to the big boys up
top. DHH, Rick or James or someone…

It does make sense.