FactoryGirl覆盖关联对象的属性

这可能很简单,但我无法在任何地方找到一个例子。

我有两个工厂:

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: "test@test.com"}) 

或类似的东西,但我不能正确的语法。 错误:

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

我知道我可以通过首先创建用户然后将其与配置文件相关联来实现此目的,但我认为必须有更好的方法。

或者这将工作:

 p = FactoryGirl.create(:profile, user: FactoryGirl.create(:user, email: "test@test.com")) 

但这似乎过于复杂。 是否有更简单的方法来覆盖关联的属性? 这是什么语法?

根据FactoryGirl的创建者之一,您无法将动态参数传递给关联助手( 在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: "test@test.com"}) 

我认为你可以使用回调和瞬态属性来完成这项工作。 如果你修改你的个人资料工厂:

 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: "test@test.com") 

不过,我还没有测试过它。

通过首先创建用户解决它,然后配置文件:

 my_user = FactoryGirl.create(:user, user_email: "test@test.com") my_profile = FactoryGirl.create(:profile, user: my_user.id) 

因此,这几乎与问题中的相同,分为两行。 唯一真正的区别是对“.id”的显式访问。 用Rails测试5。