Factory Girl (Bot) Associations
In this article we will go through how to generate the data for has_one, has_many and polymorphic associations using FactoryGirl. Every association will be described with an example, so you can get the idea how to create more complex factories with no pain.
Generating the data for has_one association
Setting up has_one association is quite easy, you can define it within the factory. If the factory name is the same as the association name, the factory name can be left out. For example:
FactoryBot.define do
factory :story do
# story attributes
author
end
end
Also, you can specify a different factory and override attributes:
FactoryBot.define do
factory :story do
# story attributes
association :author, factory: :user, first_name: "Jon"
end
end
It's possible to specify different strategies for creating the association:
association :author, factory: :user, strategy: :build
Keep in mind that this won't save an associated object in the database.
Generating the data for has_many association
Generating the data for a has_many association is a bit more complicated. You can define new factory and use after(:create) callback to create a list of associations. Let's see how to do it in this example:
FactoryBot.define do
# user factory without associated stories
factory :user do
# user attributes
factory :user_with_stories do
transient do
stories_count 10
end
after(:create) do |user, evaluator|
create_list(:stories, evaluator.stories_count, user: user)
end
end
end
end
Attribute stories_count is a transient and available in attributes of the factory and in the callback via the evaluator. Now, you can create a user with stories with the option to specify how many stories we want:
create(:user_with_stories).stories.length # 10
create(:user_with_stories, stories_count: 15).stories.length # 15
Please note that every story will have a unique id, but in order to have other attributes unique, you need to generate different values for each story.
You can achieve that using the sequence as an example:
FactoryBot.define do
factory :story do
# story attributes
sequence(:title) { |n| "Title#{n}" } # Unique title for every story
association :author, factory: :user, first_name: "Jon"
end
end
There is also an interesting gem that can help you generate unique values called faker.
Generating the data for polymorphic associations
A polymorphic association can be a bit confusing. Hopefully, this example will help you understand it better. Let's say you have next classes with polymorphic associations:
class Profile
belongs_to :profileable, polymorphic: true
end
class Account
belongs_to :accountable, polymorphic: true
end
class User
has_one :profile, as: :profileable
has_one :account, as: :accountable
end
When creating the factories for the models that have the polymorphic model, you simply create the polymorphic model in an after(:create) block and specify the polymorphicable to be the model the factory is for:
FactoryBot.define do
factory :user, class: User do
# user attributes
after(:create) do |user|
create(:account, accountable: user)
create(:profile, profileable: user)
end
end
end
And... that's it!
Thank you for reading this article.
If you are interested in reading more interesting articles about Rails be sure to subscribe to our newsletter!
Interested in similar topics? Be sure to check our take on Rspec let vs before, Rspec Setup and FactoryGirl - create vs build vs buldstubbed.