让我们想象一下,我运行了一个假想的艺术商店,里面有几个模特(模特我指的是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
的{{1}}或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
,一切都像魔法一样。
答案 0 :(得分:1)
我找到了一种方法来做我想要的,相当优雅。我需要对Product
MVC的每个部分进行更新。
型号:
attr_accessible: artwork_ids
我必须将art_ids添加到attr_accessible,因为之前没有包含它。
查看:
= check_box_tag "purchase[artwork_ids][]", artwork.id, artwork.purchase == @purchase
在我看来,每个艺术作品都有一个check_box_tag
的数组。我无法使用check_box
,因为没有检查框会导致隐藏值“true”被发送而不是艺术品ID。但是,这使我无法从购买中删除所有艺术作品。执行update
时,如果取消选中每个复选框,则params[:purchase]
哈希将没有:artwork_ids
条目。
控制器:
params[:purchase][:artwork_ids] ||= []
添加此选项可确保设置该值,并具有删除所有现有关联所需的效果。但是,这会导致令人讨厌的rspec失败
Purchase.any_instance.should_receive(:update_attributes).with({'these' => 'params'})
失败,因为:update_attributes
实际收到{"these"=>"params", "artwork_ids"=>[]})
。我尝试在视图中设置hidden_value_tag
,但无法让它工作。我认为这个问题值得一个新问题。
答案 1 :(得分:0)
最好使用将购买模型作为连接表并具有多对多关联。
以下是您的用例示例。
客户模式
has_many :purchases
has_many :artwork, :through => :purchase
艺术品模型
has_many :purchases
has_many :customers, :through => :purchase
购买模式
belongs_to :customer
belongs_to :artwork
购买模型应包含customer_id和artwork_id。
您还需要创建一个允许您创建新购买对象的购买控制器。
当客户按下购买按钮时,它将创建一个新的购买对象,其中包括customer_id和artwork_id。这允许您在客户和他们购买的艺术品之间创建关联。您还可以使用price_paid列来保存客户在购买时支付的价格。
如果您需要更多帮助,可以使用以下方法研究加入多对多关联:
希望有所帮助