2011-10-04 22 views
23

Tôi có hai mô hình (ModelA và ModelB) và FactoryGirl cho mỗi nhà máy. Tôi muốn nhà máy cho ModelB có thể (A) tạo dữ liệu thử nghiệm, và để (B) xây dựng (mà không lưu vào cơ sở dữ liệu) dữ liệu mẫu để hiển thị cho khách hàng. Tôi gặp sự cố khi (A) hoạt động do xác thực Rails trong các mô hình của tôi.Xác nhận Rails Bypass khi tạo đối tượng FactoryGirl

ModelA:

class ModelA < ActiveRecord::Base 
    belongs_to :model_b 
    validates_presence_of :model_b 
end 

Factory cho 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 

Factory cho ModelB

FactoryGirl.define do 
    factory :model_b do 
    some_attr "goodbye" 
    end 
end 

Tôi không thể tạo các đối tượng từ các nhà máy mà không nhận lỗi xác nhận:

ruby> FactoryGirl.create :model_a 
ActiveRecord::RecordInvalid: Validation failed: ModelB can't be blank 

Dường như FactoryGirl đang cố gắng để lưu các đối tượng nhà máy trước khi lưu assocations của nó. Tôi nhận ra rằng tôi có thể có nhà máy cho ModelB tạo ra ModelA liên quan của nó (thay vì xây dựng nó) - tuy nhiên, tôi sẽ mất tính linh hoạt khi có thể sử dụng nhà máy ModelA để xây dựng dữ liệu mẫu hoặc lưu dữ liệu thử nghiệm. Cách khác, tôi có thể loại bỏ các xác nhận; nhưng sau đó tôi sẽ không có hiệu lực.

Bất kỳ tùy chọn nào khác?

Trả lời

17

Tôi nhìn vào một vài giải pháp.

Một là để tạo ra một proxy tùy chỉnh, được minh họa ở đây: http://codetunes.com/2009/11/05/fixtures-without-validation-with-factory-girl

khác là để thiết lập một khối to_create trong nhà máy:

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 
+0

Khắc phục tuyệt vời. Giúp tôi rất nhiều. –

+0

Proxy tùy chỉnh không còn hoạt động FYI nữa. default_strategy đã bị xóa ở đây: https://github.com/thoughtbot/factory_girl/commit/76235313240c17db663fe7f2868d7f0ecdea72d8#diff-2856f806bf47808e13bc8dc0baf374db – Geesu

+0

Hoặc xem: https://github.com/thoughtbot/factory_girl/issues/578 –

2

Xác thực vòng tròn này không phải là một ý tưởng hay. Làm thế nào bạn có ý định xây dựng các đối tượng thực sự trong cơ sở dữ liệu? Imho đơn giản là không thể.

Trước tiên, bạn cần lưu các đối tượng vào cơ sở dữ liệu, ID được chỉ định bởi cơ sở dữ liệu và chỉ sau khi xây dựng/lưu đối tượng, bạn có thể tham chiếu đối tượng bằng cách sử dụng ID trong khóa ngoài. Vì vậy, để có thể tham khảo một bản ghi trong cơ sở dữ liệu, nó phải được lưu trước tiên. Nhưng nếu xác thực yêu cầu ID của bạn phải được biết và hiện diện trước khi lưu ...

Quan hệ belongs_to, khóa ngoài nằm trong bảng và sau đó bạn có thể thể hiện nhu cầu cần có chìa khóa. Với mối quan hệ has_one, khóa ngoài nằm trong bảng khác và bạn không thể biểu thị xác thực rằng phần tử phải có mặt. Vì vậy, bạn nên xóa xác thực từ ModelB.

Hy vọng điều này sẽ hữu ích.

[UPDATE]

Bạn có cố gắng viết:

FactoryGirl.define do 
    factory :model_a do 
    some_attr "hello" 
    model_b 
    end 
end 
+0

Xin cảm ơn phản hồi của bạn. Bạn nói đúng, tôi không nên có xác nhận thông tư. Tôi đã cập nhật bài đăng gốc của mình. Với những sửa chữa, vấn đề ban đầu của tôi vẫn còn: Tôi không thể tạo các trường hợp nhà máy của ModelA bằng cách sử dụng 'FactoryGirl.create: model_a'. – maxenglander

+0

Tôi đã làm theo lời khuyên mới nhất của bạn và thay thế thuộc tính lười biếng của tôi bằng 'association: model_b,: method =>: build' - đây chỉ là những gì tôi cần! Cảm ơn bạn. – maxenglander

24

Làm thế nào về điều này?

FactoryGirl.build(:model_a).save(validate: false) 

EDIT: Như Scott McMillin ý kiến ​​dưới đây, nếu bạn muốn đối tượng được xây dựng như là một biến, bạn có thể làm điều này:

model_a = FactoryGirl.build(:model_a) 
model_a.save(validate: false) 
+0

Không biết về OP nhưng điều này đã giúp tôi! Cảm ơn! –

+1

Lưu ý: Một lớp lót này trả về một TrueClass chứ không phải một cá thể ModelA. Nếu bạn cần sử dụng cá thể làm: 'model_a = build (: model_a); model_a.save (xác thực: sai) ' –

Các vấn đề liên quan