Factory Girl is powerful as heck, but it seems like some of the errors for has_many associations just come up as an error from FactoryGirl’s syntax runner. There are a bunch of different causes that come up from a few google searches, but here’s one that I hadn’t seen answered anywhere else. This could be caused by ruby 2.1, or by using the FactoryGirl beta 3.0.0, I’m not too sure.
I have an association:
to_do_item belongs_to to_do_list
to_do_list has_many to_do_items
I wanted a to_do_list factory that contained several to_do_items. You set this up with the after(:create)callback. For more information, see this excellent blog post from thoughtbot. My factory read like this:
FactoryGirl.define do
factory :to_do_list do
end
factory :three_item_list, parent: :to_do_list do
after(:create) do |list|
to_do_items << FactoryGirl.create(:to_do_item, {content: "item one", to_do_list: list, created_at: (DateTime.now - 1.hour)})
to_do_items << FactoryGirl.create(:to_do_item, {content: "item two", to_do_list: list, created_at: (DateTime.now - 1.day)})
to_do_items << FactoryGirl.create(:to_do_item, {content: "item three", to_do_list: list, created_at: (DateTime.now)})
end
end
end
The factory itself passes a .valid? call, but trying to use it threw the SyntaxRunner exception. After reading and re-reading the FactoryGirl readme a bunch, on a whim I tried out:
FactoryGirl.define do
factory :to_do_list do
end
factory :three_item_list, parent: :to_do_list do
after(:create) do |list|
list.to_do_items << FactoryGirl.create(:to_do_item, {content: "item one", to_do_list: list, created_at: (DateTime.now - 1.hour)})
list.to_do_items << FactoryGirl.create(:to_do_item, {content: "item two", to_do_list: list, created_at: (DateTime.now - 1.day)})
list.to_do_items << FactoryGirl.create(:to_do_item, {content: "item three", to_do_list: list, created_at: (DateTime.now)})
end
end
end
and my specs stopped throwing a SyntaxRunner exception and started failing as I’d expect them to. So there you go, it might be necessary in a has_many association to explicitly name the receiving object.