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ます。私のcreateまたはupdateコントローラーメソッドでは、新しいものを既存Purchaseのものに関連付けたいと思います。PurchaseArtwork

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、すべてが魔法のように機能するという、他の方向からの動作のようなものです。

4

2 に答える 2

1

私は自分がやりたいことをする方法を考え出しました。それはかなりエレガントです。ProductMVCの各部分を更新する必要がありました。

モデル:

attr_accessible: artwork_ids

以前は含まれていなかったため、attr_accessibleにartwork_idsを追加する必要がありました。

意見:

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

私の見解では、各アートワークの配列に。が付いていcheck_box_tagます。check_boxチェックボックスをオンにしないと、アートワークIDの代わりに「true」の非表示の値が送信されるという落とし穴のため、使用できませんでした。ただし、これにより、購入からすべてのアートワークを削除するという問題が残ります。を実行するときupdateに、各チェックボックスをオフにすると、ハッシュにエントリparams[:purchase]がありません。:artwork_ids

コントローラ:

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

これを追加すると、値が設定されることが保証され、既存のすべての関連付けを削除するという望ましい効果が得られます。ただし、これにより、実際に受信Purchase.any_instance.should_receive(:update_attributes).with({'these' => 'params'})したため、厄介なrspecエラー が失敗します。代わりにビューにを設定しようとしましたが、機能しませんでした。このニットは新しい質問に値すると思います。:update_attributes{"these"=>"params", "artwork_ids"=>[]})hidden_value_tag

于 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 に答える