DEV Community

n350071πŸ‡―πŸ‡΅
n350071πŸ‡―πŸ‡΅

Posted on • Edited 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


Enter fullscreen mode Exit fullscreen mode

πŸ‘ 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


Enter fullscreen mode Exit fullscreen mode


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


Enter fullscreen mode Exit fullscreen mode

πŸ”— 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