扶手:我怎样一个事务协会的has_many添加到现有的模式? [英] Rails: How do I transactionally add a has_many association to an existing model?

查看:143
本文介绍了扶手:我怎样一个事务协会的has_many添加到现有的模式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

让我们想象一下我运行一个虚构的艺术商店与一对夫妇模型(和模型,我指的是Rails的任期不艺​​术期限作为裸体模特),看起来是这样的:

Let's imagine I run an imaginary art store with a couple models (and by models I'm referring to the Rails term not the arts term as in nude models) that looks something like this:

class Artwork < ActiveRecord::Base
  belongs_to :purchase
  belongs_to :artist
end

class Purchase < ActiveRecord::Base
  has_many :artworks
  belongs_to :customer
end

艺术品创建并晚些时候它被包含在购买。在我的创建购买更新控制器方法我会喜欢新的关联购买与现有艺术品

The Artwork is created and sometime later it is included in a Purchase. In my create or update controller method for Purchase I would like to associate the new Purchase with the existing Artwork.

如果在艺术品不存在,我可以做的 @ purchase.artworks.build @ purchase.artworks.create ,但这些都假设我要创建一个新的艺术品而我不是。我可以像这样加上现有的艺术作品:

If the Artwork did not exist I could do @purchase.artworks.build or @purchase.artworks.create, but these both assume that I'm creating a new Artwork which I am not. I could add the existing artwork with something like this:

params[:artwork_ids].each do |artwork|
  @purchase.artworks << Artwork.find(artwork)
end

然而,这不是事务。该数据库立即更新。 (当然,除非我在创建控制器,在这种情况下,我认为它可能会做事务性,因为 @purchase 不存在,直到我称之为保存,但这并不能帮我换更新)。有也是 @ purchase.artwork_ids = 的方法,但这是直接为好。

However, this isn't transactional. The database is updated immediately. (Unless of course I'm in the create controller in which case I think it may be done "transactionally" since the @purchase doesn't exist until I call save, but that doesn't help me for update.) There is also the @purchase.artwork_ids= method, but that is immediate as well.

我觉得这样的事情会在更新操作工作,但它是非常不雅。

I think something like this will work for the update action, but it is very inelegant.

@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 在我的模型的另一个方向,然后调用结果= @ artwork.save ,一切工作就像魔术。

What I'm looking for is something like the way it would work from the other direction where I could just put accepts_nested_attributes_for in my model and then call result = @artwork.save and everything works like magic.

推荐答案

我已经想出了一个办法做我想要的相当优雅。我需要进行更新,我的产品 MVC的各个部分。

I have figured out a way to do what I want which fairly elegant. I needed to make updates to each part of my Product MVC.

型号:

attr_accessible: artwork_ids

我不得不添加artwork_ids到attr_accessible,因为它不包括之前

I had to add artwork_ids to attr_accessible since it wasn't included before.

查看:

= check_box_tag "purchase[artwork_ids][]", artwork.id, artwork.purchase == @purchase

在我看来,我有一个数组与 check_box_tag 每个艺术品。我不能使用 check_box 因为疑难杂症的地方没有检查框会导致真正的隐藏价值,而不是被发送的作品ID的。然而,这给我留下了从采购删除所有作品的问题。当执行更新,如果我取消每个复选框,然后在 PARAMS [:购买] 散列不会有:artwork_ids 输入

In my view I have an array for each artwork with a check_box_tag. I couldn't use check_box because of the gotcha where not checking the box would cause a hidden value of "true" to be sent instead of an artwork id. However, this leaves me with the problem of deleting all the artwork from a purchase. When doing update, if I uncheck each check box, then the params[:purchase] hash won't have an :artwork_ids entry.

控制器:

params[:purchase][:artwork_ids] ||= []

添加此保证的值被设置,并且将具有除去所有现存的关联的所期望的效果。但是,这会导致一个讨厌失败的RSpec
Purchase.any_instance.should_receive(:update_attributes方法)。随着({'这些'=&GT;'参数'})失败,因为:update_attributes方法实际收到的 {这些=&gt;中PARAMS,artwork_ids=&GT; []})。我试图在视图中设置一个 hidden_​​value_tag 代替,但不能让它开始工作。我觉得这尼特是值得一个新的问题。

Adding this guarantees that the value is set, and will have the desired effect of removing all existing associations. However, this causes a pesky rspec failure Purchase.any_instance.should_receive(:update_attributes).with({'these' => 'params'}) fails because :update_attributes actually received {"these"=>"params", "artwork_ids"=>[]}). I tried setting a hidden_value_tag in the view instead, but couldn't get it to work. I think this nit is worthy of a new question.

这篇关于扶手:我怎样一个事务协会的has_many添加到现有的模式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆