factory_girl association validations
-
20-09-2019 - |
Question
I have an issue where I have a parent model Foo
, which both has_many :bars
and has_many :bazes
. Finally, I also have a join model BarBaz
which belongs_to :bar
and belongs_to :baz
. I want to validate all bar_bazes so that its bar and baz both belong to the same foo. But I can't seem to figure out a way to define a factory for this model that would be valid.
Factory.define(:bar) do |bar|
bar.association(:foo)
end
Factory.define(:baz) do |baz|
bar.association(:foo)
end
Factory.define(:bar_baz) do |bar_baz|
baz_bar.association(:foo)
baz_bar.association(:bar)
baz_bar.association(:baz)
end
I get an invalid record error when I try to create the latter, because the bar and baz factory_girl tries to associate it each have their own foo. Am I screwed?
Solution
So after hours of beating my head against this issue, I think I finally have a solution. It's pretty insane though, so hopefully someone else can still show me where I'm being stupid.
Factory.define :foo do |foo|
end
Factory.define :bar do |bar|
end
Factory.define :baz do |baz|
end
Factory.define :foo_with_baz do |foo|
foo.after_create { |foo| Factory(:baz, :foo => foo) }
end
Factory.define :bar_baz do |bar_baz|
bar_baz.bar {|bar| bar.association(:bar, :foo => Factory(:foo_with_baz))
bar_baz.after_build {| bar_baz| bar_baz.baz_id = bar_baz.foo.bars.first.id }
end
The key issue being that there needs to be a foo in the database already you can get at through the factories alone, since you can use local variables or arbitrary ruby code in factories.rb (as far as I can tell).
OTHER TIPS
The insaneness of creating factories with deeply nested associations led me to create fixie which lets you create test records using ActiveRecord. It runs during the db:test:prepare
step. I use it to eliminate the need for fixtures. You can continue to use factories for easier-to-build objects.