how to build on ActiveRecord association before parent object has an id?
I have a model, Foo, that has_many Bars. It has a virtual attribute, current_baz, that returns the baz attribute of the latest Bar from the association (if one exists). I'd like to define Foo.current_baz= so that one can say my_foo.update_attributes(:current_baz => 7), and in partic开发者_开发技巧ular, I'd like it to work when a new Foo is created. That way I can say
Foo.new(:current_baz => 7, ...)
and it should do
self.bars.build(:baz => 7)
Of course, it doesn't work, because the new Foo doesn't have an id yet and thus the new Bar isn't valid. I know how to work around this in a controller, creating first the Foo and then the Bar and wrapping both in a transaction. But I'd really like to keep this logic in the model if possible. It seems almost possible. Does anyone have any suggestions?
There are a few ways to do this, but one way that I've done in the past (particularly if you can rely on there being only one new bar object at a time is to make an instance variable for the unsaved bar, inside foo. So then, to sketch that out, you'd say:
if self.new?
@new_bar = bar.new
@new_bar.baz = new_current_baz_value
else
self.bars.build(:baz => 7)
end
Then, you add an after_save handler that says
if @new_bar
@new_bar.foo = self
@new_bar.save
@new_bar = nil
end
Then, finally, when you call current_baz, you need to test for the existenceof a new_bar, like so:
if @new_bar
return @new_bar.baz
else
return self.bars.last.baz
end
Does that make sense?
精彩评论