テストを書いていてレコードを一度に複数用意してかつ、呼び出し時にそれぞれのレコードの属性を異なるものにしたいことが時々ある。 FactoryBotでそれを実現する方法についてまとめておく。
create_list
で複数のレコードを作成しつつ、ブロックで任意の属性に異なる値を設定することができる。
インスタンスを上書きたい場合はsaveメソッドなどを使い、再度更新する必要があるので注意。
twenty_somethings = create_list(:user, 10) do |user, i|
user.date_of_birth = (20 + i).years.ago
user.save!
end
また、上記のようにcreate_list
で一度保存したインスタンスに対して再度更新処理をかけると2n回クエリが発行されてしまう。build_list
を使用することでクエリの発行回数を抑えることができる
twenty_somethings = build_list(:user, 10) do |user, i|
user.date_of_birth = (20 + i).years.ago
user.save!
end
あらかじめ対象の属性値を含む配列(データセット)を定義しておき、map
メソッドのブロック内でcreate
することで任意の属性に異なる値を設定することができる。
[ { name: '田中', role: '管理者' }, { name: '山田', role: '編集者' }, { name: '渡辺', status: '閲覧者' } ].map do |restaurant_name|
create(:user, name: attributes[:name], status: attributes[:status])
end
build_list
を使用する方法のように使い分ける。
FactoryBotの内部実装を確認してみた時にメモしたリンク集。