FactoryGirlで多対多の関連データを一緒に生成する

以下の記事を参考にさせていただきました。

FactoryGirl で多対多のアソシエーションをつくる

http://blog.inouetakuya.info/entry/2013/12/28/205008

FactoryGirlsのアソシエーションのとこは以下から。

http://www.rubydoc.info/gems/factory_girl/file/GETTING_STARTED.md#Associations

factory_girl で最低限知っておきたい4つの使い方(@sasata299さん)

http://blog.livedoor.jp/sasata299/archives/51931175.html

手順

ここの記事で非常にわかりやすくまとめていただいていました。

  • まず1個目のモデル(Category)のfactoryを普通に定義する。
  • 次に、2個目のモデル(Book)を定義するfactoryブロックの中でafter()を使う。
  • after(:create)に渡すブロックのなかでアソシエーション用のオブジェクトを作成して、2つのオブジェクトのインスタンスを引数に取らせる

via: http://woshidan.hatenablog.com/entry/2014/09/06/194843

Userがbuildまたはcreateされたときに、それに関連するDetailsも生成されるようにしたいという想定で。

spec/factories/users.rbを以下のようにすればok!

FactoryGirl.define do
  factory :user do
    sequence(:email) { |n| "ex#{n}@ex.com" }
    sequence(:password) { |n| "password#{n}" }

    # createされたあとに関連モデルデータもcreateする
    after(:create) do |user|
      create(:user_details,
             user: user,
             detail: create(:detail))
    end

  end
end

これでuser_detailsを作成するときにリファレンスでuserdetailも関連付けされたデータを生成できる。

after(:create)after(:build)かは、用途によって使い分けるのがいいと思う。自分はcreateのときにはDBに保存するってところから確実に結びついたデータがほしいということで、buildのときには、関連データはその場で作った他のデータをくっつけたりする場面で必要なときに使ったりできるようにした方が便利だなと思ってafter(:create)にした。