Rails 在参数中为 M 到 M 关联形成传递数组

Rails Forms Passing Array in Params for M to M Associaton

编辑:本质上是希望通过这样的内容:

{
  'tabled_id' : '1',
  'recipes' : [{
        { 'recipe_id' : '3',
          'quantity' : '2'
        }
        { 'recipe_id' : '5',
          'quantity' : '1'
        }
  }]
}

而且我认为我应该在控制器方面params.require(:order).permit(:table_id, {recipes:, [:id,:quantity]} )

我正在学习 Rails 构建一个订购系统,但我一直在尝试为传递数量的订单构建一个表单。其中 Orders 是 Restaurant 的嵌套资源。

我的模型是这样的:

class Restaurant < ActiveRecord::Base
    has_many :orders
    has_many :recipes, dependent: :destroy
end

class Order < ActiveRecord::Base
    belongs_to :restaurant
    has_many :order_recipes, dependent: :destroy
    has_many :recipes, through: :order_recipes
end

class Recipe < ActiveRecord::Base
    belongs_to :restaurant
    has_many :order_recipes
    has_many :orders, through: :order_recipes
end

查看:

    <%= form_for([@restaurant, @order]) do |order_form| %>
        <%= order_form.label :Table_Number %>
        <%= order_form.number_field :table_id %>

        <h3>Recipes: </h3>
        <br>

        <% @restaurant.recipes.each do |recipe| %>
            <%= order_form.fields_for :recipe, recipe do |r| %>
                <%= r.label recipe.name %>
                <%= r.hidden_field :id %>
                <%= r.number_field :quantity %>
            <% end %>
        <% end %>

        <%= order_form.submit(@order.new_record? ? "Create Order" : "Edit Order", class: "btn btn-success") %>
    <% end %>

这将生成一个看起来正确的表单,但不会传递所有参数。假设我有 3 个食谱。我将它们的数量分别设置为 2、3、4,并将 table_id 设置为 1。当我检查参数时,我看到只有最后一个配方及其数量已通过。 params[:order] => {"table_id"=>"1", "recipe"=>{"id"=>"4", "quantity"=>"4"}} 我需要能够发送所有食谱及其指定数量。此外,我在此问题中使用已接受的答案来访问数量列:Rails 4 Accessing Join Table Attributes

当你多次提交 fields_for :recipes 时,fields_for 方法并不知道你发送了一个数组。因此它将命名参数,就好像它只是一个实例,所以只有最后一个实例会通过。你得把菜谱数组交给fields_for,这样它才能给参数命名,这样rails再拿起来的时候就知道是数组了(docs ). 这是因为浏览器中的表单参数默认不支持嵌套。实际参数是平面键值参数。 Rails 有一些关于如何命名参数的 naming conventions,因此它们将自动被强制转换为数组。

<%= form_for([@restaurant, @order]) do |order_form| %>
    <%= order_form.label :Table_Number %>
    <%= order_form.number_field :table_id %>

    <h3>Recipes: </h3>
    <br>


    <%= order_form.fields_for :recipes, @restaurant.recipes do |r| %>
      <%= r.label recipe.name %>
      <%= r.hidden_field :id %>
      <%= r.number_field :quantity %>
    <% end %>


    <%= order_form.submit(@order.new_record? ? "Create Order" : "Edit Order", class: "btn btn-success") %>
<% end %>