Rails 4 Strong Params has_many с JSON

Я пытаюсь передать 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"]}

Я не думаю, что это был бы лучший способ сделать это, поэтому я пока оставлю вопрос без ответа в надежде, что это будет лучшая практика.


person TomJ    schedule 11.07.2013    source источник
comment
Другой способ сделать это... вы можете найти его более чистым (или нет!) - stackoverflow.com/questions/21490255/   -  person Nigel Sheridan-Smith    schedule 28.09.2014


Ответы (1)


Обходной путь в этом случае не нужен. 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. Включите ключ *_attributes в свой JSON. В вашем случае измените ключ 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
    

С помощью вложенных атрибутов можно добиться еще большего. Для получения дополнительной информации см. ActiveRecord::NestedAttributes в Rails API< /а>

person Alex Braha Stoll    schedule 21.08.2013