Rails 4 Strong Params has_many with JSON

时间:2013-07-11 02:36:14

标签: ruby-on-rails json ruby-on-rails-4 strong-parameters

我正试图在客户端传递json并让rails负责处理对象的创建。

以下是我的模特:

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搞砸了,或者红宝石.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"]}

我认为这不是最好的方式,所以我现在暂时不回答这个问题,希望有最好的做法。

1 个答案:

答案 0 :(得分: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
    
  4. 使用嵌套属性可以实现更多功能。有关详细信息,请参阅ActiveRecord::NestedAttributes at Rails API