Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
4
Help us understand the problem. What is going on with this article?
@Kolosek

Factory Girl (Bot) Associations

More than 3 years have passed since last update.

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.

Interested in similar topics? Be sure to check our take on Rspec let vs before, Rspec Setup and FactoryGirl - create vs build vs buldstubbed.

Originally published on kolosek.com.

4
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
4
Help us understand the problem. What is going on with this article?