2012-04-10 24 views
11

Vì vậy, tôi được thừa nhận là người mới sử dụng Rails và tôi đang gặp phải vấn đề khá phổ biến nhưng tôi không thể tìm thấy câu trả lời ở đây.Tạo liên kết trước khi ghi lại được lưu

Tôi có một mô hình Foo như thế này:

class Foo < ActiveRecord::Base 
    has_many :bars 
end 

Bars belongs_to Foo, tất cả những gì hoạt động. Bây giờ tôi muốn tạo ra một Foo và xây dựng Bar cùng một lúc. Như thế này:

f = Foo.new(:baz => 'baz') 
bars.each do |b| 
    f.bars.build(:bizzy => b[:bizzy]) 
end 
f.save 

Tôi biết điều này sẽ không hoạt động vì bản ghi gốc không tồn tại, vì vậy liên kết không tồn tại nhưng phải có cách để thực hiện việc này. Tôi đã tạm thời giải quyết vấn đề này bằng cách chỉnh sửa điều này:

f = Foo.new(:baz => 'baz') 
f.save 
f = Foo.find(:first, :conditions => {:baz => 'baz'}) 
bars.each do |b| 
    f.bars.create(:bizzy => b[:bizzy]) 
end 

Nhưng điều đó không sạch sẽ và xung quanh khó chịu.

Cách phù hợp để thực hiện việc này là gì?

Trả lời

10

Trong dòng đầu tiên, bạn chỉ có thể sử dụng create thay vì new. Bạn không cần f.bars.create hoặc f.bars.build, vì đối tượng bar đã tồn tại. Tôi sẽ làm việc này:

f = Foo.create(:baz => 'baz') 

bars.each do |b| 
    f.bars << b 
end 

Cá nhân tôi sẽ không lặp qua các bars, nhưng chỉ cần sử dụng update_all:

f = Foo.create(:baz => 'baz') 
bars.update_all(:foo_id => f.id) 

Edit: nó có thể làm điều này mà không lưu các bản ghi đầu tiên. Điều này phù hợp với tôi:

f = Foo.new(:baz => 'baz') 

bars.each do |b| 
    f.bars << b 
end 

f.save 
+0

Huh, tôi có thể thề rằng điều đó là không thể. Bạn là đúng mặc dù, sau khi tôi thử nghiệm nó một lần nữa, nó làm việc như một say mê. Cảm ơn! – Eugene

+1

Chạy vào cùng một vấn đề và nhận ra rằng đối với tùy chọn cuối cùng (f = Foo.new), tôi phải xóa ': foo_id, remove: presence => true' trên mô hình Bar (trong mã của riêng tôi). – migu

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