0

コントローラーのスキニーアップに関して私が見たほとんどの質問は、単純なモデルの関係を扱っています。私の質問は、複数のパラメーターとそれに関連付けられた配列を使用して多対多のフォームを更新する場合、すべてをモデル メソッドに移動してタスクを簡素化するにはどうすればよいですか? たとえば、以下のとてつもなく大きなコントローラーを見てください。この不浄な混乱に対処する最も簡単な方法は何ですか? 私は構文的に完璧な答えを探しているわけではありませんが、これを進める方向性について一般的なコンセンサスが必要です。

def update
  @shipment = Shipment.joins(:products).find(params[:id], :readonly => false)
  @shipment.update_attributes(params[:shipment])
  @shipment_products = params[:product_shipments]
  @product_shipment_array= array_from_hash(@shipment_products)


  @shipment.product_shipments.each do |product_shipment|
    product_shipment.update_attributes(:qty_shipped => params[:product_shipments][product_shipment.id.to_s][:qty_shipped], :pickup_item => params[:product_shipments][product_shipment.id.to_s][:pickup_item])
  end
  @product_shipment_array.each do |p|
    if  p['old_pickup_item'] == "true" and p['pickup_item'].to_i==0
      @difference = (p['qty_shipped'].to_i)
      Product.mark_open_shipment(@difference, p['product_id'])

    elsif p['old_pickup_item'] == "false" and p['pickup_item'].to_i==1
      @difference = -(p['old_qty_shipped'].to_i)
      Product.mark_open_shipment(@difference, p['product_id'])
    else
      @difference = -(p['old_qty_shipped'].to_i - p['qty_shipped'].to_i)
      Product.mark_open_shipment(@difference, p['product_id'])
    end

  end

  respond_with @shipment, :location => shipments_url
end

私のモデルでは、このようなモデルメソッドを宣言したい

Class Shipment < ActiveRecord::Base
  .
  .
  .      
  def update_shipment_attributes
    #all business logic
  end

end

コントローラーを次のようなものにすることを期待して:

def update
  @shipment = Shipment.joins(:products).find(params[:id], :readonly => false)
  @shipment.update_attributes(params[:shipment])
  @shipment_products = params[:product_shipments]

  Shipment.update_shipment_attributes

  respond_with @shipment, :location => shipments_url     
end
4

1 に答える 1

0

目的を達成するために使用できるいくつかのアプローチを次に示します。

  1. ネストされたフォームと の使用を検討してくださいaccepts_nested_attributes_for。ネストされた属性を使用すると、コントローラーeditメソッドは、1 つの@shipmentインスタンス変数のみを、shipping_products のネストされたコレクションと共有する必要があります。
  2. updateアクションのみを呼び出すことを検討してくださいupdate_attributes。ネストされた属性を適切に使用している場合、これは必要な唯一のモデル呼び出しである必要があります。これは、そのshipment_products.
  3. shipment_productsモデルで、after_saveコールバックを使用して、開いている出荷をマークします。ただし、shipping_products モデルでは(大文字の)という単語を使用しないでください。代わりに、 call との関係にProduct依存する必要があります。product_shipments のインスタンス メソッドにリファクタリングする必要があります。コールバックと update_attributes はすべて 1 つのトランザクションで実行されるため、原子性が保証されます。belongs_toproduct.mark_open_shipment(difference)difference
于 2012-10-16T04:15:55.343 に答える