我有两个模型(ModelA和ModelB),以及每个模型的FactoryGirl工厂。我希望ModelB的工厂能够(A)创建测试数据,并且(B)构建(不保存到数据库)样本数据以显示给客户。由于我的模型中的Rails验证,我无法让(A)工作。
MODELA:
class ModelA < ActiveRecord::Base
belongs_to :model_b
validates_presence_of :model_b
end
ModelA的工厂:
FactoryGirl.define do
factory :model_a do
some_attr "hello"
model_b { FactoryGirl.build :model_b }
end
end
ModelB
class ModelB < ActiveRecord::Base
has_one :model_a
end
ModelB的工厂
FactoryGirl.define do
factory :model_b do
some_attr "goodbye"
end
end
如果没有验证错误,我无法从这些工厂创建对象:
ruby> FactoryGirl.create :model_a
ActiveRecord::RecordInvalid: Validation failed: ModelB can't be blank
FactoryGirl似乎在保存工厂对象之前尝试保存工厂对象。我意识到我可以让ModelB的工厂创建其关联的ModelA(而不是构建它) - 然而,我将失去能够使用ModelA工厂来构建样本数据或保存测试数据的灵活性。或者,我可以删除验证;但后来我没有验证。
还有其他选择吗?
答案 0 :(得分:25)
这个怎么样?
FactoryGirl.build(:model_a).save(validate: false)
编辑:如下面的Scott McMillin注释,如果您希望将构建的对象作为变量,则可以执行以下操作:
model_a = FactoryGirl.build(:model_a)
model_a.save(validate: false)
答案 1 :(得分:17)
我研究了几个解决方案。
一种是创建自定义代理,如下所示: http://codetunes.com/2009/11/05/fixtures-without-validation-with-factory-girl
另一种是在工厂设置to_create
块:
FactoryGirl.define do
factory :model_a do
model_b { FactoryGirl.build :model_b }
to_create do |instance|
instance.model_b.save!
instance.save!
end
end
end
答案 2 :(得分:2)
此循环验证不是一个好主意。你打算如何在数据库中构建真实对象? Imho这根本不可能。
首先需要将对象保存到数据库,ID由数据库分配,只有在构建/保存对象后才能使用外键中的ID引用对象。因此,为了能够引用数据库中的记录,必须先将其保存。但是,如果验证要求在保存之前知道并出现ID ......
在belongs_to
关系中,外键在表中,然后您可以表示需要存在密钥。使用has_one
关系时,外键位于另一个表中,并且您无法表示该元素应存在的验证。因此,您应该从ModelB
删除验证。
希望这有帮助。
[UPDATE]
你有没有尝试写作:
FactoryGirl.define do
factory :model_a do
some_attr "hello"
model_b
end
end
答案 3 :(得分:1)
我也遇到了同样的问题,当模型的关联无法保存时,模型无法保存。
也许试试这个:https://github.com/thoughtbot/factory_girl/issues/369?