I'm sorry to have to revert to the issues list here, but I can't for the life of me find any documentation on creating has_many
relationships in FG 2.0. After some experimentation I found the solution below, but I don't know if this is the "right" way to do it:
class Post < ActiveRecord::Base
has_many :comments
end
class Comment < ActiveRecord::Base
belongs_to :post
end
FactoryGirl.define do
factory :comment do
body 'This is a comment'
end
factory :post do
title 'This is a Post'
comments { FactoryGirl.create_list(:comment, 2) }
# or, to create only one => comments { [FactoryGirl.create(:comment)] }
end
end
Factory.create :post
One problem is that I won't know if you called build
or create
when you factoried (nice, right?) your post, but this will always create the comments. So I played with the syntax a bit to get association
in there instead and came up with this:
factory :post do
title 'This is a Post'
comments { [association(:comment)] }
end
Is that the right way to do it? GETTING_STARTED
has a great reference for just about everything you can do with FG except this one case. Thanks!
By the way, if that later method is the correct one I'd be happy to update the docs myself an issue a pull request.
+1 something like this is needed
Creating records for a has_many
association is sort of tricky, for a couple reasons:
First, there's always a chicken-and-egg problem doing this in a relational database, because one record has to exist before the other. You can't create records in separate tables simultaneously, and one table has to hold the primary key of the other.
Second, there's no knowing what kind of validations or callbacks are in place on the models in question, so it's hard to know if the collection needs to be saved or unsaved.
If you're validating that at least member is present in the collection, you can try passing in a list of unsaved records (using Factory.build
).
If you're not validating anything about the collection, I'd recommend doing it in an after_create callback.
After talking about this with @jferris, it seems like the ideal syntax may be something like this:
FactoryGirl.define do
factory :user, :aliases => [:author]
factory :comment do
author
post
factory :old_comment do
created_at { 1.year.ago }
end
end
factory :post do
factory :commented_post do
comments(2) # this would create two `:comment`s
# alternatively...
comments # this would create one `:comment`
old_comments(2, :body => 'something static') # this would create two `:comment`s, both with body of 'something static'
old_comments # this would create one `:old_comment`
end
end
end
I've added more documentation in this commit: https://github.com/thoughtbot/factory_girl/commit/9c6c252d0fb58ba6321d8db56778bb3469ff5a77
It includes tests (since they're a great form of documentation) but the primary example is in the GETTING_STARTED document.
While it's beneficial to discuss syntactical improvements and ways to make this more straightforward, I think that's better handled in a separate pull request when an implementation is started; for now, this focuses on documentation and this commit should handle that request.
Thanks everyone for their contribution to the discussion!
Most helpful comment
Creating records for a
has_many
association is sort of tricky, for a couple reasons:First, there's always a chicken-and-egg problem doing this in a relational database, because one record has to exist before the other. You can't create records in separate tables simultaneously, and one table has to hold the primary key of the other.
Second, there's no knowing what kind of validations or callbacks are in place on the models in question, so it's hard to know if the collection needs to be saved or unsaved.
If you're validating that at least member is present in the collection, you can try passing in a list of unsaved records (using
Factory.build
).If you're not validating anything about the collection, I'd recommend doing it in an after_create callback.