factory_bot と必須 association

Published: 2023/4/23


背景

has_one な association は、子供テーブルの側では、 optional: true を付与しない、つまり、親を必須としてモデルの association を定義する場合が多い。

factory_bot にてこのノリでやろうとすると、親のファクトリー定義にて子供を指定したいが、子供は親がないと save! できず、なので create(:parent) した際にまず create(:child) 相当が実行され、エラーになってしまう。

対策

strategy: :build な association を、親側で定義すると良い。

実際、上記のケースでは、

class User < ActiveRecord::Base
  has_one :profile
  validates :email, uniqueness: true, presence: true
end

class Profile < ActiveRecord::Base
  belongs_to :user, dependent: :destroy, required: true
end

上記のようなモデルがあった場合に、以下のようにするとよい、ということで close されている。

FactoryGirl.define do
  factory :user do
    email 'user@email.com'
    password '123456'
    password_confirmation '123456'
    association :profile, factory: :profile, strategy: :build
  end

  factory :profile do
    first_name 'First'
    last_name 'Last'
    type 'Consumer'
  end
end

このように定義をすると、おそらく、 association における autosave (autosave 宣言なし) の挙動になり、 create(:user) した際に内部で呼ばれる user.save! によって、良い感じに生成される、はず。(参考: factory_bot の基本動作)


Tags: factory-botrails

関連記事