views:

36

answers:

1

When working with activerecord I notice that while constructing associations, the reciprocal association is provided automatically only if the reciprocal model has already been saved. If it has not yet been saved, this reciprocal association must be defined manually. I am wondering if this is intentional or a bug, since the only difference in it working or failing is whether the reciprocal model has been saved or not.

I hopefully clarified this with the three scenarios described in the following gist.

http://gist.github.com/527046

I would expect Scenario 1 to work without the extra assignment step shown in Scenario 3. It doesn't.

+3  A: 

The reason is fairly simple - when you create an object through an association where the parent object is not yet saved, its associated foreign key can't have a value, because the associated record isn't saved yet. By means of example:

# Registration announcement is not saved at this point, so it has no ID.
@a1 = @e1.build_registration_announcement(:announcement => "Please bring a favorite baked dish.")
# Registration is built without a registration_announcement_id, as @a1 has no ID to pass on.
@a1.registrations.build(:contact_email => "[email protected]", :adults => 1)
#registration doesn't know about its unsaved registration_announcement parent

# Registration announcement is created and saved. ID exists.
@a2 = @e2.create_registration_announcement(:announcement => "Fall house cleaning!")
# Since the Registration announcement has an ID, registration_announcement_id is set on the built associated registration
@a2.registrations.build(:contact_email => "[email protected]", :adults => 5)
#registration knows about its saved registration_announcement parent

It's a little unexpected, since you might logically expect Rails to keep the object association around and then assign the association foreign key at save-time, but it doesn't seem to work that way.

Chris Heald
I was just hoping that Rails might magically maintain the association. I am able to define it wherever necessary just as I did in Scenario 3; however, it seems there would be sufficient metadata available in the context of the build for ActiveRecord to do this on my behalf. This would benefit my code, making it a bit cleaner.
Mario