2012-12-13 41 views
17

Tôi có mối quan hệ has_many tiêu chuẩn (Đặt trước có nhiều Đơn đặt hàng) với xác thực rằng Đặt chỗ không được lưu mà không có ít nhất một Đơn đặt hàng. Tôi đang cố gắng để tái tạo điều này với các nhà máy FactoryGirl của tôi nhưng xác nhận là ngăn cản tôi làm như vậy.FactoryGirl has_many liên kết với xác nhận

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

class Order < ActiveRecord::Base 
    belongs_to :booking 
end 

Dưới đây là thông số kỹ thuật nhà máy FactoyGirl của tôi cho từng mô hình theo sau trang wiki GitHub của FactoryGirl.

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 

Khi tôi cố gắng chạy FactoryGirl.create(:booking_with_orders) từ spec của tôi, tôi nhận được:

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

Nó có vẻ như việc kiểm tra về việc phê chuẩn đang chạy ngay cả trước khi before(:create) [...] mà về mặt lý thuyết sẽ tạo ra đơn đặt hàng cho các đặt phòng.

This post khuyên bạn không nên thêm has_many mối quan hệ với nhà máy của bạn nhưng tôi muốn giải quyết vấn đề này nếu có cách tốt để làm điều đó.

Xin cảm ơn trước.

Trả lời

30

Wat? Không thể nào? Không có gì.

Chỉ cần thay đổi mã của bạn để một cái gì đó như thế này:

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

Ý bạn là 'booking.orders <<' nhưng ngược lại, đây là câu trả lời cho tôi. Cảm ơn! – Jalada

+0

Rất tiếc! cố định nó, cảm ơn cho chỉ nó ra – jassa

+0

tuyệt vời! Cảm ơn rất nhiều! – gayavat

0

Điều này có vẻ giống như một quan sát quá đơn giản nhưng những gì bạn đang cố gắng làm là có hiệu lực chắc chắn rằng Order tồn tại trước khi Booking, đó là không thể, như Order không thể tồn tại mà không booking_id của nó (nghĩa là Booking nhu cầu sẽ được tạo đầu tiên).

Không có gì sai với mối quan hệ has_many trong nhà máy của bạn, đó là xác thực của bạn, đó là vấn đề. Điều này hiện có hoạt động trong ứng dụng của bạn không? Làm thế nào để bạn lưu hồ sơ của bạn trong trường hợp đó? Luồng tạo đơn hàng và đặt chỗ là gì?

Ngay cả những người khét tiếng accepts_nested_attributes_for sẽ không giúp bạn ở đây.

Lời khuyên của tôi là suy nghĩ lại chiến lược lưu và xác thực bản ghi của bạn để chiến thuật trở nên lành mạnh hơn một chút.

+0

Xin cảm ơn, đây là một xem xét tốt nhưng mọi thứ đều hoạt động trong ứng dụng của tôi với xác thực. Đây là luồng của tôi: '@booking = Booking.new (params [: booking])' '@booking.orders << Order.new (params [: order]) '' @ booking.save'. –

+0

@ErikNomitch Bạn đã thử gọi lại 'after (: build)' thay vì 'before (: create)'? Xác thực của bạn chính xác như thế nào khi đặt 'Đặt chỗ'? Tôi đoán điểm mấu chốt của vấn đề là FactoryGirl có thể muốn tạo ra các đối tượng này một cách độc lập, điều này có ý nghĩa từ một điểm kiểm tra, nhưng khi bạn tạo chúng như bạn vừa ghi trong bình luận, chúng sẽ được tạo ra với nhau. Loại khớp nối này thường dẫn đến đau đầu. – regulatethis

2

Cất cánh từ câu trả lời @ jassa, nếu bạn chỉ cần thêm một đĩa đơn (bắt buộc) kỷ lục liên kết với một thuộc tính cụ thể, mô hình này làm việc cho tôi :

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 
Các vấn đề liên quan