2

让我们想象一下,我经营一家假想的艺术商店,里面有几个模特(模特我指的是 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. 在我的createupdate控制器方法中,Purchase我想将新Purchase的与现有的Artwork.

如果Artwork不存在,我可以做@purchase.artworks.buildor @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,一切都像魔术一样工作。

4

2 回答 2

1

我已经想出了一种方法来做我想做的事情,而且相当优雅。我需要对ProductMVC 的每个部分进行更新。

模型:

attr_accessible: artwork_ids

我不得不将artifact_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在视图中设置 a ,但无法使其正常工作。我认为这个 nit 值得提出一个新问题。

于 2012-12-05T01:16:05.357 回答
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 列来保存客户在购买时支付的价格。

如果您需要更多帮助,您可以使用 :through 研究加入多对多的协会。

希望能帮助到你

于 2012-12-04T19:08:51.703 回答