DEV Community

n350071🇯🇵
n350071🇯🇵

Posted on • Updated on

[RSpec] Factorybot transient & trait with argument

🤔 Situation

You want to make a user with a book that title is 'Ruby'.

class User
  has_many: books
end
class Book
  belongs_to: user
end

👍 Solution

  • trait: you can run the process
  • trait with arguments: It is DEPRECATED, we should use transient instead.
  • transient: you can define and pass arguments with the block
FactoryBot.define do
  factory :user, class: User do
    trait :with_book
      transient do
        # 🦄1. default value when you use :with_book trait
        # 🦄2. Dont't assign just 'Agile'. see also: https://thoughtbot.com/blog/deprecating-static-attributes-in-factory_bot-4-11
        title { 'Agile' }
      end
      after(:build) do |user, evaluator|
        user.book = FactoryBot.create(:book, title: evaluator.title)
      end
    end
  end

  factory :book, class Book do
    sequence(:title) { |n| "book no.#{n}" } # 🦄 default value
  end

end
let!(:user) { create(:user, :with_book, title: 'Ruby') }

🔗 Parent Note

Top comments (2)

Collapse
 
samuelfaure profile image
Samuel-Zacharie FAURE

Thank you for this small snippet, it was quite useful!

Collapse
 
mxdavis profile image
Malki Davis

Very helpful! Small thing -- there should be a do after trait :with_book