Ruby on Rails: has_many through frustrations
I'm having a frustrating problem with a has_many through: namely the fact that the through models are not created until save. Unfortunately, I need to set data on these models prior to saving the parent.
Here's the loose setup:
class Wtf < ActiveRecord::Base
belongs_to :foo
belongs_to :bar
end
class Bar < ActiveRecord::Base
has_many :wtfs
has_many :foos, :through => :wtfs
end
class Foo < ActiveRecord::Base
has_many :wtfs
has_many :bars, :through => :wtfs
def after_initialize
Bar.all.each do |bar|
bars << bar
end
end
开发者_JAVA技巧end
Everything is fine except that I need to access the "wtf"'s prior to save:
f = Foo.new => #
f.bars => [list of bars]
empty list here
f.wtfs => []
f.save! => true
now I get stuff
f.wtfs => [list of stuff]
I even went so far as to explicitly create the wtfs doing this:
def after_initialize
Bar.all.each do |bar|
wtfs << Wtf.new( :foo => self, :bar => bar, :data_i_need_to_set => 10)
end
end
This causes the f.wtfs to be populated, but not the bars. When I save and retrieve, I get double the expected wtfs.
Anyone have any ideas?
I think you have the right idea with creating the Wtfs
directly. I think it will turn out OK if you just set the bars at the same time:
def after_initialize
Bar.all.each do |bar|
wtfs << Wtf.new(:bar => bar, :data_i_need_to_set => 10) # Rails should auto-assign :foo => self
bars << bar
end
end
Rails should save the records correctly because they are the same collection of objects. The only drag might be that if rails doesn't have the smarts to check if a new Bar
record in the bars collection already has a Wtf
associated, it might create one anyway. Try it out.
Couldn't you write a before_save
handler on Wtf that would set the data you need to set? It would have access to both the foo and bar, if needed.
You could set the method that populates bar to an after_create, like this:
class Foo < ActiveRecord::Base
has_many :wtfs
has_many :bars, :through => :wtfs
after_create :associate_bars
def associate_bars
Bar.all.each do |bar|
bars << bar
end
end
end
This would make the wtfs be already be created when this method is called.
精彩评论