1

クライアント側でjsonを渡し、レールにオブジェクトの作成を処理させようとしています。

ここに私のモデルがあります:

class Order < ActiveRecord::Base
  has_many :order_items, :autosave => true
  belongs_to :menu_session
end

class OrderItem < ActiveRecord::Base
  belongs_to :order
  has_one :menu_item
end

コントローラ

class OrderController < ApplicationController
 #POST /order/create
 def create
   @order = Order.new(order_params)
   @order.save
 end

private
  def order_params
    params.require(:order).permit(:comments, :menu_session_id, :order_items => [:menu_item_id])   
  end
end

json データ:

{'order': {'comments': 'none', 'menu_session_id': '9', 'order_items':[{'menu_item_id': '5'}, {'menu_item_id': '5'}]}};

JavaScript

var data = {};
data.order = {'comments': 'none', 'menu_session_id': '9', 'order_items':[{'menu_item_id': '5'}, {'menu_item_id': '5'}]};
$.post('http://localhost:3000/order/create', orders, function(){}, 'json');

最後に、エラー ログ:

Started POST "/order/create" for 127.0.0.1 at 2013-07-10 22:30:36 -0400
Processing by OrderController#create as JSON
Parameters: {"order"=>{"comments"=>"none", "menu_session_id"=>"9", "order_items"=>{"0"=>{"menu_item_id"=>"5"}, "1"=>{"menu_item_id"=>"5"}}}}
Completed 500 Internal Server Error in 52ms

ActiveRecord::AssociationTypeMismatch (OrderItem(#28109220) expected, got Array(#16050620)):
app/controllers/order_controller.rb:5:in `create'

明らかに、私の json が台無しになっているか、ruby .permit が間違っています。しかし、私はこれのバリエーションでしばらく遊んでいましたが、うまくいきません。公式ドキュメントはこれに挑戦していないようで、ここで見つけたすべての例はフォームを扱っています。

何が起こっているのか誰にも分かりますか?このアプローチを試すのは私が最初ではありません。


アップデート:

次の変更を加えて回避しました。

class OrderController < ApplicationController

  #POST /order/create
  def create
    @order = Order.new(order_params)
    order_items = order_item_params
    order_items.each do |item|
      @order.order_items << OrderItem.new(menu_item_id: item)
    end
    @order.save
  end


  private
    def order_params
      params.require(:order).permit(:comments, :menu_session_id)   
    end
    def order_item_params
      params.require(:order_items)
    end
end

json:{"order":{"comments":"none","menu_session_id":"9"},"order_items":["5","5"]}

これが最善の方法だとは思わないので、ベストプラクティスがあることを期待して、今のところ質問には答えないままにします.

4

1 に答える 1

3

この場合、回避策は必要ありません。ActiveRecord は、params ハッシュを介して直接子要素を自動的に作成する方法を提供します。これを行うには、次の手順に従います。

  1. モデルでネストされた属性を構成する

    class Order < ActiveRecord::Base
      # autosave is already enabled with accepts_nested_attributes_for
      has_many :order_items
      belongs_to :menu_session
    
      accepts_nested_attributes_for :order_items
    end
    
  2. JSON に *_attributes キーを含めます。あなたの場合、 order_items キーをorder_items_attributesに変更します

    {'order': {'comments': 'none', 'menu_session_id': '9', 'order_items_attributes':[{'menu_item_id': '5'}, {'menu_item_id': '5'}]}};
    
  3. コントローラーで、新しいキーを受け入れる許可を作成します

    def order_params
      params.require(:order).permit(:comments, :menu_session_id, :order_items_attributes => [:menu_item_id])   
    end
    

ネストされたアトリビュートを使用すると、さらに素晴らしいことが実現できます。詳細については、Rails API の ActiveRecord::NestedAttributes を参照してください。

于 2013-08-21T04:14:20.453 に答える