FactoryGirl 覆盖关联对象的属性
Posted
技术标签:
【中文标题】FactoryGirl 覆盖关联对象的属性【英文标题】:FactoryGirl override attribute of associated object 【发布时间】:2013-04-30 10:11:24 【问题描述】:这可能很简单,但我在任何地方都找不到示例。
我有两个工厂:
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"))
但这似乎过于复杂。难道没有更简单的方法来覆盖关联的属性吗? 正确的语法是什么??
【问题讨论】:
【参考方案1】:根据 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")
【讨论】:
很好的答案。你会更新它以符合最新的 Rails 版本吗?例如。我收到“弃用警告:#ignore
已弃用,将在 5.0 中删除。”实施此答案时。
您可以使用“transient”而不是“ignore”来消除警告【参考方案2】:
我认为您可以使用回调和瞬态属性来完成这项工作。如果您像这样修改您的配置文件工厂:
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")
不过,我还没有测试过。
【讨论】:
谢谢,但我希望它适用于任何属性,所以我不想像那样为每个属性编写代码。也许没有其他人需要这个...... 我认为您的示例有错误。将after(:create)
更改为profile.user.email = evaluator.user_email unless evaluator.user_email.nil?
【参考方案3】:
通过先创建用户,然后创建个人资料来解决它:
my_user = FactoryGirl.create(:user, user_email: "test@test.com")
my_profile = FactoryGirl.create(:profile, user: my_user.id)
所以,这与问题中的几乎相同,分为两行。 唯一真正的区别是对“.id”的显式访问。 使用 Rails 5 测试。
【讨论】:
以上是关于FactoryGirl 覆盖关联对象的属性的主要内容,如果未能解决你的问题,请参考以下文章