创建FactoryGirl对象时绕过Rails验证

时间:2011-10-04 19:19:04

标签: ruby-on-rails factory-bot

我有两个模型(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工厂来构建样本数据或保存测试数据的灵活性。或者,我可以删除验证;但后来我没有验证。

还有其他选择吗?

4 个答案:

答案 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