web-dev-qa-db-ja.com

FactoryGirlの関連付けに属性を設定する際にパラメーターを渡します

関連するモデルに属性を設定するために使用されるファクトリーにパラメーターを渡したいのですが。関連するモデルは工場内で作成されます。

結合テーブルTxLinkを介してそれ自体への多対多リンクを持つトランザクションモデルがあります。 2つのTransactionオブジェクトと2つをリンクするTxLinkを作成するlink = FactoryGirl.create(:link_red_to_sub, sub: 10, red: 7)を呼び出します。

最後にunits: subがあるため、以下の関連付け行でエラーが発生します。エラーは「特性が定義されていません」です。代わりにunits: { sub }(括弧付き)を試しましたが、サイコロはありませんでした。

factory :tx_link do
    units "9.99"

    factory :link_red_to_sub do
      ignore do
        sub 0
        red 0
      end
      units { red }

      association :giver, factory: :transaction, units: sub
      association :taker, factory: :redemption, units: red
    end
  end
30
rigyt

Factory_girlのassociationヘルパーは動的プロパティ引数をとることができませんが、動的属性を使用して、必要に応じて関連付けをインスタンス化できます。

factory :tx_link do
  units "9.99"

  factory :link_red_to_sub do
    transient do
      sub 0
      red 0
    end
    units { red }

    giver { create(:transaction, units: sub) }
    taker { create(:redemption, units: red) }
  end
end

これの唯一の欠点は、givertakerの関連付けが、tx_linkを構築している戦略に関係なく、作成戦略を使用することです。つまり、本質的にはattributes_forおよびbuild_stubbedは、tx_linkファクトリでは正しく機能しません。

私が提供した例にはバージョン4.5.0が必要です。

37
Joe Ferris

ジョーの答えを拡張して、ビルドと作成を区別できるようにします。

factory :tx_link do
  units "9.99"

  factory :link_red_to_sub do
    ignore do
      sub 0
      red 0
    end
    units { red }

    giver { build(:transaction, units: sub) }
    taker { build(:redemption, units: red) }

    after(:create) do |link_red_to_sub|
      link_red_to_sub.giver.save!
      link_red_to_sub.taker.save!
    end
  end
end
26
BKewl