Rails 4 Strong Params has_many with JSON

。_饼干妹妹 提交于 2019-12-04 15:57:08

问题


I'm attempting to pass json up on the client side and have rails take care of handling the object creation.

Here are my models:

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

Controller

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

The json data:

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

The 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');

Finally, the error log:

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'

Clearly, either my json is messed up or the ruby .permit is wrong. However, I've been playing with variations of this for a while now and cannot get it to work. The official documentation doesn't seem to venture into this, and every example I have found here deals with forms.

Anyone have any idea what is going on? I can't be the first to try this approach.


UPDATE:

Worked around it by making the following changes:

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"]}

I don't think this would be the best way to do it, so I'm going to leave the question unanswered for now in hopes there is a best practice.


回答1:


The workaround is not necessary in this case. ActiveRecord provides an automagic way of creating child elements directly through the params hash. In order to accomplish this, follow the steps bellow:

  1. Configure Nested Attributes in the model

    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. Include a *_attributes key in your JSON. In your case, change the order_items key to order_items_attributes

    {'order': {'comments': 'none', 'menu_session_id': '9', 'order_items_attributes':[{'menu_item_id': '5'}, {'menu_item_id': '5'}]}};
    
  3. In your controller, make permit accept your new key

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

There is some more awesomeness possible to accomplish with Nested Attributes. For further information, see ActiveRecord::NestedAttributes at Rails API



来源:https://stackoverflow.com/questions/17584142/rails-4-strong-params-has-many-with-json

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!