web-dev-qa-db-ja.com

関連オブジェクトのFactoryGirlオーバーライド属性

これはおそらくばかげて単純ですが、どこにも例を見つけることができません。

私には2つの工場があります。

FactoryGirl.define do
  factory :profile do
    user

    title "director"
    bio "I am very good at things"
    linked_in "http://my.linkedin.profile.com"
    website "www.mysite.com"
    city "London"
  end
end

FactoryGirl.define do 
  factory :user do |u|
    u.first_name {Faker::Name.first_name}
    u.last_name {Faker::Name.last_name}

    company 'National Stock Exchange'
    u.email {Faker::Internet.email}
  end
end

私がしたいのは、プロファイルを作成するときにユーザー属性の一部を上書きすることです。

p = FactoryGirl.create(:profile, user: {email: "[email protected]"})

または似たようなものですが、構文が正しくありません。エラー:

ActiveRecord::AssociationTypeMismatch: User(#70239688060520) expected, got Hash(#70239631338900)

最初にユーザーを作成し、それをプロファイルに関連付けることでこれを実行できることはわかっていますが、もっと良い方法があるはずだと思いました。

またはこれは動作します:

p = FactoryGirl.create(:profile, user: FactoryGirl.create(:user, email: "[email protected]"))

しかし、これは過度に複雑に見えます。関連する属性をオーバーライドする簡単な方法はありませんか?これの正しい構文は何ですか?

25
bobomoreno

FactoryGirlの作成者の1人によると、動的引数を関連付けヘルパーに渡すことはできません( FactoryGirlの関連付けの属性を設定する際のパラメーターを渡す )。

ただし、次のようなことができるはずです。

FactoryGirl.define do
  factory :profile do
    transient do
      user_args nil
    end
    user { build(:user, user_args) }

    after(:create) do |profile|
      profile.user.save!
    end
  end
end

それから、あなたが望むようにそれを呼び出すことができます:

p = FactoryGirl.create(:profile, user_args: {email: "[email protected]"})
23
BKewl

コールバックと一時的な属性でこれを機能させることができると思います。プロファイルファクトリを次のように変更した場合:

FactoryGirl.define do
  factory :profile do
    user

    ignore do
      user_email nil  # by default, we'll use the value from the user factory
    end

    title "director"
    bio "I am very good at things"
    linked_in "http://my.linkedin.profile.com"
    website "www.mysite.com"
    city "London"

    after(:create) do |profile, evaluator|
      # update the user email if we specified a value in the invocation
      profile.user.email = evaluator.user_email unless evaluator.user_email.nil?
    end
  end
end

その後、次のように呼び出して、必要な結果を得ることができます。

p = FactoryGirl.create(:profile, user_email: "[email protected]")

まだテストはしていません。

6
Wally Altman

最初にユーザーを作成し、次にプロファイルを作成することで解決しました:

my_user = FactoryGirl.create(:user, user_email: "[email protected]")
my_profile = FactoryGirl.create(:profile, user: my_user.id)

したがって、これは質問とほぼ同じで、2行に分割されます。実際の違いは、「。id」への明示的なアクセスのみです。 Rails 5.でテスト済み。

3
Kjell