はじめに
先日、factory_botのFactoryBot.create_listメソッドで詰まったので記録しておきます。
例ではUserモデルとPostモデルが1対多で対応していることとします。
やりたかったこと
FactoryBot.create_listは複数のテストデータを生成するfactory_botのメソッドです。それぞれ異なるPostを持ったUserオブジェクトを複数作ろうとしました。
FactoryBot.create_list(
:user,
5,
post: FactoryBot.create(:post)
)
しかし、生成されるpostはどれも同じもので、想定する挙動ではありませんでした。
何がダメだったのか
どうやら、create_listの挙動としてある一つの属性に対してランダムな値を入れることはできないようです。上の例では、post: FactoryBot.create(:post)の箇所で同じpostが使いまわされているようでした。
以下のgithubのイシューに私と同じ場面に遭遇した方のコメントがありました。
https://github.com/thoughtbot/factory_bot/issues/787

解決策
上記のイシューでは、あらかじめ用意しておいた配列に対してmapを使い、それぞれの要素に対してFactoryBot.createするという解決策が提示されていました。eachでも良さそうですね。以下がコメントにあったコードです。
%w(NYC Boston SF Austin).map do |tb_location|
FactoryBot.create(:location, city: tb_location)
end
余談ですが、そのときの私はtimesを使いました。欲しい挙動にも依りますが、確実に違う値を入れたいというときは上の方が良さそうですね。
5.times do
FactoryBot.create(:user, post: Factory.create(:post))
end
おわり
binding.pryで引っかかる箇所を特定してからも時間がかかってしまいました。こういった細かな挙動を押さえておくのは地道な積み重ねですね。