2012-12-13 152 views
17

我有一個標準的has_many關係(預訂有很多訂單),並驗證預訂在沒有至少一個訂單的情況下無法保存。我試圖用我的FactoryGirl工廠複製這個,但驗證正在阻止我這樣做。FactoryGirl has_many與驗證關聯

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

class Order < ActiveRecord::Base 
    belongs_to :booking 
end 

這裏是我的FactoyGirl出廠規格爲每個模型從FactoryGirl的GitHub的wiki頁面緊隨其後。

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關係添加到您的工廠,但是我想解決這個問題,無論如何,如果有一個好的方法來做到這一點。

在此先感謝。

回答

30

Wat?不可能?一點也不。

只要改變你的代碼是這樣的:

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

您的意思是'booking.orders <<',否則,這是我的答案。謝謝! – Jalada

+0

哎呀!修好了,謝謝指出 – jassa

+0

優秀!非常感謝! – gayavat

0

這似乎是一個過於簡單化的觀察,但你想做什麼實際上是確保該Order存在Booking,這是不可能的面前,因爲Order離不開其booking_id存在(這意味着Booking需求首先創建)。

工廠中的has_many關係沒有任何問題,這是您的驗證問題。這目前是否在你的應用程序中工作?如何在這種情況下保存你的記錄?創建訂單和預訂的流程是什麼?

即使臭名昭着的accepts_nested_attributes_for也不會幫你在這裏。

我的建議是重新考慮您的記錄保存和驗證策略,使其更加理智。

+0

謝謝,這是一個很好的考慮,但一切都在我的應用與驗證工作。這裏是我的流程:'@booking = Booking.new(params [:booking])'''booking.orders << Order.new(params [:order])''@ booking.save'。 –

+0

@ErikNomitch你有沒有嘗試'後(:構建)'回調,而不是'(之前)::?您對「Booking」設置的驗證究竟如何?我想這個問題的真正癥結在於FactoryGirl可能希望孤立地創建這些對象,這從測試的角度來看是有意義的,但是當您在註釋中創建它們時,它們會一起創建。這種耦合通常會導致頭痛。 – regulatethis

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