How to specify the association with factory_bot?

24,626

Solution 1

You should use explicit associations instead of implicit ones:

#spec/factories/post.rb
FactoryBot.define do
  factory :post do
    association :user    # <<<--- here the change
    body Faker::Movie.quote
    posted_at "2018-04-03 13:33:05"
  end
end

#spec/factories/user.rb
FactoryBot.define do 
  factory :user do 
    first_name 'Jake'
  end
end

https://github.com/thoughtbot/factory_bot/blob/master/GETTING_STARTED.md#associations

Solution 2

Another option is to use #trait method within the parent.

FactoryBot.define do
  factory :post do
    user nil
    body Faker::Movie.quote
    posted_at "2018-04-03 13:33:05"
  end
end

FactoryBot.define do 
  factory :user do 
    first_name 'Jake'
  end

  trait :with_post do
    after(:create) do |user|
      create(:post, user_id: user.id)
    end
  end
end

FactoryBot.create(:user, :with_post)

Solution 3

Here we have another solution in case your association name and factory name is different then you can follow below syntax.

#spec/factories/post.rb
FactoryBot.define do
  factory :post do
    association :author, factory: :user
    body Faker::Movie.quote
    posted_at "2018-04-03 13:33:05"
  end
end

in case your factory name is author and model name is user then you can use above syntax

Share:
24,626

Related videos on Youtube

Jake McAllister
Author by

Jake McAllister

Updated on January 11, 2022

Comments

  • Jake McAllister
    Jake McAllister over 2 years

    For example I have two models a user and a post. A post belongs_to a user and a user has many posts

    #spec/factories/post.rb
    FactoryBot.define do
      factory :post do
        user
        body Faker::Movie.quote
        posted_at "2018-04-03 13:33:05"
      end
    end
    
    #spec/factories/user.rb
    FactoryBot.define do 
      factory :user do 
        first_name 'Jake'
      end
    end
    

    Using Rspec in a test I want to do this:

    user = create(:user, first_name: 'Barry') #id 1
    post = create(:post, user: user)
    

    I would expect that the user_id of post to be 1 however it is creating another user prior and the user_id is 2.

    How can you specify the association when you are creating the object with factory_bot / factory_girl?

    • abax
      abax about 6 years
      What does post.user.inspect and User.all return after you make the post?
    • Jake McAllister
      Jake McAllister about 6 years
      post.user is User
    • Jake McAllister
      Jake McAllister about 6 years
      and User.all is equal two users
    • emptywalls
      emptywalls about 6 years
      Can you post your complete spec? Do you have any kind of authentication involved? If you have to login to run the spec, that could be the source of the other user.
    • emptywalls
      emptywalls about 6 years
      Also, what the first_names in the records? Are they both Jake?
    • Jake McAllister
      Jake McAllister about 6 years
      no its just that as a plain spec
    • Jake McAllister
      Jake McAllister about 6 years
      to your second question first one has a first name of 'barry' and the second one has a first name of 'jake'
    • Humayun Naseer
      Humayun Naseer over 3 years
      factory :post do here post is pointing the actual model or this is created here ? & if this one is model & located within a module how can we locate it ?
  • Ri1a
    Ri1a over 3 years
    Are there more arguments on why you should use explicit associations instead of implicit ones?
  • Fran Martinez
    Fran Martinez over 3 years
    Using explicit associations is the only way to be able to override the attributes of the associated object. When the association is implicit, FactoryBot will create an associated object on which you don't have control of its attributes (it will automatically create an associated object based on the factory for that object). github.com/thoughtbot/factory_bot/blob/master/…