Michael Kovacs' photos More of Michael Kovacs' photos
Recommend Me Cable Car Software logo

Thursday, August 31, 2006

Rails realities part 19 (Relation assignments)

Many folks out there may not know this but you can set relations on AR objects in more than one way. Unless there's another I'm missing I know of 2 ways:
  1. parent.child = Child.find(:first)

  2. parent.child_id = Child.find(:first).id

When you save the parent object after each of the above statements you'll have created the parent-child relationship in the database. The second way is probably not as well known as the first, but it is very useful when updating a HABTM relationship.
Allow me to demonstrate...

In your view you have:

< %parent.children.each do |child|%>
< %=check_box_tag 'parent[child_ids][]', child.id, child_selected%> Child value < %=child.to_s%>
< %end%>

When you submit a form containing this field tag you'll receive all in your parameter set:
{'parent' => {'child_ids' => [2, 3, 7]}}

With which you can simply update the parent like so:

And all of your related HABTM objects will be set and updated once you save the parent object.

With that groundwork laid have a look at the following code:
parent = Parent.new
parent.child = Child.find(1)
parent.child_id = 3

What do you think will be saved in the database for this relation? The child with the id 1 or 3?

Of course the answer is 1. Huh? Don't get it? Yeah me neither. I stumbled across this bug, or inconsistency today while working on reassigning a related object to a new value.

I wrote this small unit test to reproduce what I was seeing in my app. The usage of setting "child_id" will work as long as the related object is null. I haven't checked yet to see if this is a bug or not and will update if it is already known. I'm using rails 1.1.6.

Be careful out there!


Post a Comment

<< Home

This page is powered by Blogger. Isn't yours?