views:

10

answers:

1

Hi,

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 particular, 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?

+1  A: 

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?

jasonpgignac
Perfect sense, thank you!
korinthe