这可能很简单但我找不到任何例子。
我有两家工厂:
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"))
但这看起来过于复杂。是否有更简单的方法来覆盖关联的属性? 这个的正确语法是什么?
答案 0 :(得分:22)
根据FactoryGirl的创建者之一,您无法将动态参数传递给关联助手(Pass parameter in setting attribute on association in 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"})
答案 1 :(得分:6)
我认为你可以使用回调和瞬态属性来完成这项工作。如果你修改你的个人资料工厂:
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")
我还没有测试过它。
答案 2 :(得分:3)
首先创建用户,然后创建个人资料:
解决它my_user = FactoryGirl.create(:user, user_email: "test@test.com")
my_profile = FactoryGirl.create(:profile, user: my_user.id)
所以,这与问题几乎相同,分为两行。 唯一真正的区别是对“.id”的显式访问。 用Rails 5测试。