Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to specify the association with factory_bot?

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?

like image 767
Jake McAllister Avatar asked Apr 27 '18 11:04

Jake McAllister


People also ask

What is trait in FactoryBot?

FactoryBot's traits are an outstanding way to DRY up your tests and factories by naming groups of attributes, callbacks, and associations in one concise area. Imagine defining factories but without the attributes backed by a specific object.

Why is it a FactoryBot?

If you were wondering why exactly we use Factory Bot, the answer is that it makes our tests more convenient to write and more understandable to read. In addition to Factory Bot, the Faker gem can help take away some of the tedium of having to create test data values.

What is FactoryBot Ruby?

Factory Bot, originally known as Factory Girl, is a software library for the Ruby programming language that provides factory methods to create test fixtures for automated software testing.


3 Answers

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

like image 74
Fran Martinez Avatar answered Oct 16 '22 08:10

Fran Martinez


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)
like image 9
andriy-baran Avatar answered Oct 16 '22 08:10

andriy-baran


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

like image 5
uzaif Avatar answered Oct 16 '22 09:10

uzaif