2010-05-30 33 views
40

Tôi có một mô hình Foo mà has_many 'Bar'. Tôi có một factory_girl nhà máy cho mỗi đối tượng này. Nhà máy cho Bar có mối liên hệ với Foo; nó sẽ khởi tạo một Foo khi nó tạo ra Bar.Điền một liên kết với trẻ em trong factory_girl

Tôi muốn một Nhà máy tạo Foo có chứa Bar. Lý tưởng nhất Bar này sẽ được tạo ra thông qua: nhà máy thanh, và tôn trọng chiến lược xây dựng (tạo/xây dựng) được sử dụng để tạo ra Foo.

Tôi biết tôi chỉ có thể gọi: nhà máy thanh và sau đó lấy tham chiếu Foo từ Thanh mới. Tôi muốn tránh điều này; trong trường hợp thử nghiệm của tôi, đối tượng quan trọng là Foo; gọi nhà máy Bar có vẻ hơi mạch máu. Ngoài ra, tôi có thể thấy sự cần thiết cho một Foo với nhiều Bars.

Điều này có thể xảy ra trong factory_girl không? Làm thế nào để bạn xác định mối quan hệ này trong phụ huynh?

Trả lời

48

Factory.after_ hooks dường như là cách duy nhất để thực hiện thành công. Tôi đã tìm ra một cách để duy trì chiến lược xây dựng mà không trùng lặp mã:

Factory.define :foo do |f| 
    f.name "A Foo" 
    f.after(:build) { |foo| 
    foo.bars << Factory.build(:bar, :foo => foo) 
    } 
    f.after(:create) { |foo| 
    foo.bars.each { |bar| bar.save! } 
    } 
end 

Các documentation bang mà after_build sẽ được gọi trước khi after_create nếu chiến lược :create xây dựng được sử dụng. Nếu sử dụng :build thì chỉ có after_build được gọi và mọi người đều hài lòng.

Tôi cũng đã tạo một phiên bản được áp dụng chung trừu tượng at this gist để giữ mọi thứ KHÔ.

+2

hoàn hảo - đã xé toạc mái tóc của tôi. cảm ơn! – recurser

+2

Thật khó để tin rằng đây là cách tốt nhất để làm điều này nhưng nó vẫn có vẻ là trường hợp. Up-bình chọn câu trả lời này. – spier

+0

Bạn sử dụng phiên bản gist của mình như thế nào? Cách tốt nhất để kết hợp điều đó vào ứng dụng Rails là gì? –

4

Bạn có thể sử dụng phương pháp association cả hai cách:

Factory.define :foo do |f| 
    # ... 
    f.association :bar 
end 

Nếu điều đó sẽ không làm việc, bạn có thể kết hợp chúng bằng tay bằng cách sử dụng gọi lại. Dưới đây là ví dụ từ một trong các ứng dụng của tôi:

Factory.define :live_raid do |raid| 
end 

Factory.define :live_raid_with_attendee, :parent => :live_raid do |raid| 
    raid.after_create { |r| Factory(:live_attendee, :live_raid => r) } 
end 
+1

Cú pháp đầu tiên gây ra một chồng tràn/đệ quy vô hạn trong mã của tôi. Cú pháp thứ hai hoạt động tuyệt vời, ngoại trừ việc nó không tuân theo chiến lược xây dựng. –

3

FactoryGirl 4.3.0 đang kêu gọi save! vào một hiệp hội khi gọi build trên đối tượng phụ huynh, mà tôi tin rằng không có ý định trở thành hành vi đúng.

Sau khi đào qua mã FactoryGirl, thêm strategy: :build vào định nghĩa liên kết trong nhà máy có vẻ như đang tạo liên kết của tôi mà không cần gọi save!.

2

Sử dụng factory_girl-4.5.0, tạo n đối tượng trẻ em trong một nhà máy đối tượng cha

FactoryGirl.define do 
    factory :foo do 
    name "test"   

    after(:build) do |instance| 
     n.times { instance.bars << FactoryGirl.create(:bar) }   
    end 
    end 
end 
Các vấn đề liên quan