1. rh_taro

    Posted

    rh_taro
Changes in title
+FactoryBotで1対1や1対nのモデルを複数作る
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,93 @@
+# 前提として
+**Rspecで1対1の関係のモデルのテストデータを複数作りたい**
+
+うーんってなったので忘れないようついでに他のパターンも一緒にまとめました
+
+- モデルを複数作る
+- 1対1のデータを1つ作る
+- 1対nのデータを1つ作る
+- 1対1のデータを複数作る ←今回やりたくて悩んだのはここ
+- 1対nのデータを複数作る
+
+ここで例として扱うモデルは
+1対1も含めたいのでよくある1対nの親モデル`User`と子モデル`Post`にしました
+
+# まず、FactoryBotでモデルを複数作成するには
+`create_list`を使います
+
+```ruby
+FactoryBot.create_list(:post, 3)
+```
+で`Post`モデルを3つ作れる
+
+# 1対1のデータを作る
+## パターンA
+```ruby
+FactoryBot.create(:post, user: FactoryBot.create(:user))
+```
+
+## パターンB
+```ruby
+user = FactoryBot.create(:user)
+FactoryBot.create(:post, user: user)
+```
+
+## パターンC
+```ruby
+FactoryBot.create(:user) do |u|
+ FactoryBot.create(:post, user: u)
+end
+```
+
+# 1対nのデータを作る
+## パターンA
+```ruby
+user = FactoryBot.create(:user)
+FactoryBot.create_list(:post, 3, user: user)
+```
+
+## パターンB
+```ruby
+FactoryBot.create_list(:post, 3, user: FactoryBot.create(:user))
+```
+`User : Post = 1 : 3`のデータを作ってるんですが
+ぱっと見、`Post : User = 1 : 1`のデータが3つできるようにも見えません?
+自分はそう見えて「1対1のデータを複数作る」にはどうすれば、と悩みました
+
+でもまぁよくよく考えてみると妥当な挙動だと思います
+
+# 1対1のデータを複数作る
+これこれ これがやりたかった
+
+```ruby
+FactoryBot.create_list(:user, 3) do |u|
+ FactoryBot.create(:post, user: u) end
+end
+```
+
+# 1対nのデータを複数作る
+1対1のデータを複数作った時点で目的達成なのですが
+せっかくなのでついでに1対nについても考えてみました
+
+## パターンA(力技)
+```ruby
+3.times do
+ FactoryBot.create(:user) do
+ FactoryBot.create_list(:post, 3, user: user)
+ end
+end
+```
+これでもいいんですがRubocopにシバかれたので考え直してパターンBにたどり着きました
+
+## パターンB
+```ruby
+FactoryBot.create_list(:user, 3) do |u|
+ FactoryBot.create_list(:post, 3, user: u) end
+end
+```
+
+これで
+`User : Post = 1 : 3`のデータが3つ作成されます
+
+ブロック使うことでイメージとしてはcreate_listがfor文みたいでちょっと読みやすいような
+