Давайте представим, что я управляю воображаемым художественным магазином с парой моделей (и под моделями я имею в виду термин Rails, а не термин искусства, как в случае обнаженных моделей), который выглядит примерно так:
class Artwork < ActiveRecord::Base
belongs_to :purchase
belongs_to :artist
end
class Purchase < ActiveRecord::Base
has_many :artworks
belongs_to :customer
end
Создается файл Artwork
, который через некоторое время включается в файл Purchase
. В моем методе контроллера create
или update
для Purchase
я хотел бы связать новый Purchase
с существующим Artwork
.
Если бы Artwork
не существовало, я мог бы сделать @purchase.artworks.build
или @purchase.artworks.create
, но оба они предполагают, что я создаю новое Artwork
, которым я не являюсь. Я мог бы добавить существующую иллюстрацию примерно так:
params[:artwork_ids].each do |artwork|
@purchase.artworks << Artwork.find(artwork)
end
Однако это не транзакция. База обновляется мгновенно. (Если, конечно, я не нахожусь в контроллере create
, в этом случае я думаю, что это может быть сделано «транзакционно», поскольку @purchase
не существует, пока я не вызову save
, но это не поможет мне для update
.) @purchase.artwork_ids=
метод, но он также немедленный.
Я думаю, что-то подобное будет работать для действия update
, но это очень неэлегантно.
@purchase = Purchase.find(params[:id])
result = @purchase.transaction do
@purchase.update_attributes(params[:purchase])
params[:artwork_ids].each do |artwork|
artwork.purchase = @purchase
artwork.save!
end
end
За этим следует обычное:
if result
redirect_to purchase_url(@purchase), notice: 'Purchase was successfully updated.' }
else
render action: "edit"
end
То, что я ищу, это что-то вроде того, как это работало бы с другого направления, когда я мог бы просто поместить accepts_nested_attributes_for
в свою модель, а затем вызвать result = @artwork.save
, и все работает как по волшебству.