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.