N:Nの関連性のレコードをサッとつくるためのtraitを作りたい場合のtips
環境
Gemfile.lockは以下のような環境
factory_bot (6.4.4) activesupport (>= 5.0.0) factory_bot_rails (6.4.2) factory_bot (~> 6.4) railties (>= 5.0.0)
使い方
factory_botでは一時的な属性情報として transient
という機構を用意している。公式ドキュメントとしては以下のように紹介されている。
factory :user do transient do rockstar { true } end name { "John Doe#{" - Rockstar" if rockstar}" } end create(:user).name #=> "John Doe - ROCKSTAR" create(:user, rockstar: false).name #=> "John Doe"
これをtraitと組み合わせることにより、trait側に値を渡す事ができる。
利用例
たとえば以下のようなN:Nを表現するテーブルがあるとする。
この場合にbooksのレコードを作るときにshopsのレコードを指定したい場合、以下のようなtraitを作成する。
# 前提としてshopとbook_recommend_shopのFactoryBotのファイルはあること FactoryBot.define do factory :book do title { "BookTitle#{rand(100)}" } author end trait :recommend_shop do # 意図したものをセットできるようにする transient do related_recommend_shop_record { nil } end after(:create) do |self_object, evaluator| shop = evaluator.related_recommend_shop_record.nil? ? create(:shop) : evaluator.related_recommend_shop_record create(:book_recommend_shop, book: self_object, shop: shop) end end end
このように作成すれば、以下のようにshopを簡潔にしていしてつくることができる。
choice_shop = create(:shop) create(:book,:recommend_shop,related_recommend_shop_record: choice_shop)
こうすることで間の交差テーブルを意識することなくレコードをつくる仕組みを用意することができる。