Help us understand the problem. What is going on with this article?

FactoryBot Traits

More than 3 years have passed since last update.

FactoryBot はフィクスチャのツールです。
多くのフィクスチャを必要とするときは Traits が便利です。

Setup

Ruby on RailsRSpec のテスト環境を構築して確認しましょう。
今回はコンソールモードで確認します。spec/factories のファイルを修正するとコンソールで FactoryBot.reload を実行してください。

mkdir factory_bot_rails_example && cd factory_bot_rails_example/ && rails new . --api -BT
echo "gem 'pry-rails', group: [:development]" >> Gemfile
echo "gem 'factory_bot_rails', group: [:development, :test]" >> Gemfile
echo "gem 'rspec-rails', group: [:development, :test]" >> Gemfile
bundle
bundle exec rails generate rspec:install
rails generate model product title vendor state 
rails console

Usage

Trait

traitは項目をグループにすることができます。

FactoryBot.define do
  factory :product do
    title 'iPad'

    trait :modify do
      title 'iPhone'
    end
  end
end

フィクスチャにするにはトレイトのシンボルを第2引数に指定します。

例では、シンボルにmodifyを指定するとtitleiPadからiPhoneに変更されます。

[1] pry(main)> FactoryBot.reload
[2] pry(main)> FactoryBot.attributes_for(:product)
=> {
    :title => "iPad"
}
[3] pry(main)> FactoryBot.attributes_for(:product, :modify)
=> {
    :title => "iPhone"
}

Traits

traitstraitをまとめることができます。

trait :base do
  vendor 'Apple'
end

trait :activate do
  state :active
end

factory :product_activate, traits: [:base, :activate]

トレイトのシンボルをは引数に複数を指定できます。また、traitsは第1引数にシンボルを指定します。

例では、同じ値が出力されています。フィクスチャにラベルが付いて便利ですね。

[4] pry(main)> FactoryBot.reload
[5] pry(main)> FactoryBot.attributes_for(:product, :base, :activate)
=> {
     :title => "iPad",
    :vendor => "Apple",
     :state => :active
}
[6] pry(main)> FactoryBot.attributes_for(:product, :base, :activate)
=> {
     :title => "iPad",
    :vendor => "Apple",
     :state => :active
}

Transient

transientは内部で利用する変数ですが、traitと組合せて利用することができます。

transient do
  time true
end

trait :cancel do
  state :canceled
  canceled_at { Time.now if time }
end

factory :product_cancel, traits: [:base, :cancel]

traitのブロッブのブロックはある程度は自由なエリアです。 (夢が広がりますね。

例では、time変数でcanceled_atのセットを制御しました。

[7] pry(main)> FactoryBot.reload
[8] pry(main)> FactoryBot.attributes_for(:product_cancel)
=> {
          :title => "iPad",
         :vendor => "Apple",
          :state => :canceled,
    :canceled_at => 2018-02-22 22:22:22 +0900
}
[9] pry(main)> FactoryBot.attributes_for(:product_cancel, time: false)
=> {
          :title => "iPad",
         :vendor => "Apple",
          :state => :canceled,
    :canceled_at => nil
}

Tips

factoryの引数にはtraitsやブロック(doend)などを指定できます。
(traitsのブロックは1項目なら{}で1行で記述できます。)

factory :product_ipod_touch, traits: [:base, :activate] do
  title 'iPod touch'
end

traitsとブロックでフィクスチャをスッキリと管理することができます。 (キリッ

[10] pry(main)> FactoryBot.reload
[11] pry(main)> FactoryBot.attributes_for(:product_ipod_touch)
=> {
     :title => "iPod touch",
    :vendor => "Apple",
     :state => :active
}

Example

紹介したサンプルはこちらです。

FactoryBot.define do
  factory :product do
    title 'iPad'

    trait :modify do
      title 'iPhone'
    end

    transient do
      time true
    end

    trait :base do
      vendor 'Apple'
    end

    trait :activate do
      state :active
    end

    trait :cancel do
      state :canceled
      canceled_at { Time.now if time }
    end

    factory :product_activate, traits: [:base, :activate]
    factory :product_cancel, traits: [:base, :cancel]

    factory :product_ipod_touch, traits: [:base, :activate] do
      title 'iPod touch'
    end

    factory :product_ipod_nano,    traits: [:base, :activate] { title 'iPod nano' }
    factory :product_ipod_shuffle, traits: [:base, :activate] { title 'iPod shuffle' }
    factory :product_ipod_classic, traits: [:base, :activate] { title 'iPod classic' }
  end
end
ogomr
RubyKansai, naniwa.rb, DDD.rb, CoderDojo Osakasayama/Hommachi, OSS Gate Osaka, Rails Girls Osaka, Open Source Software Developers Osaka, テクノ図工部
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