はじめに
先日、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
で引っかかる箇所を特定してからも時間がかかってしまいました。こういった細かな挙動を押さえておくのは地道な積み重ねですね。