FactoryGirl与验证有很多联系

时间:2012-12-13 01:06:52

标签: ruby-on-rails factory-bot

我有一个标准has_many关系(预订有很多订单),验证如果没有至少一个订单,预订就不会被保存。我试图用FactoryGirl工厂复制这个,但验证阻止我这样做。

class Booking < ActiveRecord::Base
  has_many :orders
  validates :orders, presence: true
end

class Order < ActiveRecord::Base
  belongs_to :booking
end

以下是FactoryGirl的GitHub维基页面中每个型号的FactoyGirl工厂规格。

FactoryGirl.define do                                                    

  factory :booking do                                                                                                                   
    factory :booking_with_orders do

      ignore do                                                                                                                         
        orders_count 1                                                                                                                  
      end                                                                                                                               

      before(:create) do |booking, evaluator|                                                                                           
        FactoryGirl.create_list(:order, evaluator.orders_count, booking: booking)                                                       
      end                                                                                                                               
    end                                                                                                                                 
  end 

  factory :order do
    booking
  end

end 

当我尝试从我的规范中运行FactoryGirl.create(:booking_with_orders)时,我得到:

Failure/Error: @booking = FactoryGirl.create(:booking_with_orders)
ActiveRecord::RecordInvalid:
  Validation failed: Orders can't be blank

似乎验证检查甚至在before(:create) [...]之前就已经开始了,这在理论上会创建预订订单。

This post建议不要将has_many关系添加到您的工厂,但如果有一个好的方法,我想解决这个问题。

提前致谢。

3 个答案:

答案 0 :(得分:31)

笏?不可能?完全没有。

只需将您的代码更改为以下内容:

after :build do |booking, evaluator|
  booking.orders << FactoryGirl.build_list(:order, evaluator.orders_count, booking: nil)
end

答案 1 :(得分:2)

从@ jassa的答案中解脱,如果您只需要添加一个具有特定属性的单个(必需)关联记录,这种模式对我有用:

factory :booking do
  ignore do
    order_name "name"
  end

  after :build do |factory, evaluator|
    factory.orders << FactoryGirl.build(:order, name: evaluator.order_name, booking: nil)
  end
end

答案 2 :(得分:0)

这似乎是一种过于简单化的观察,但你要做的是确保Order存在于Booking之前,这是不可能的,因为Order没有booking_id就不能存在(意味着需要先创建Booking)。

你的工厂中的has_many关系没有任何问题,这是你的验证,这是一个问题。这目前适用于您的应用程序吗?在这种情况下,你如何保存你的记录?创建订单和预订的流程是什么?

即使臭名昭着的accepts_nested_attributes_for也不会帮助你。

我的建议是重新考虑您的记录保存和验证策略,以使其更加清晰。