Rails Forms Passing Array in Params for M to M Associaton
Edit: Essentially something like this needs to be missed:
{
'tabled_id' : '1',
'recipes' : [{
{ 'recipe_id' : '3',
'quantity' : '2'
}
{ 'recipe_id' : '5',
'quantity' : '1'
}
}]
}
And I think what I should do params.require(:order).permit(:table_id, {recipes:, [:id,:quantity]} )
on the controller side.
I'm learning Rails while building an order system and I'm stuck trying to create a form for orders that are missing quantities. Where Orders is an embedded resource for a Restaurant.
My models look like this:
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
View:
<%= 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 %>
This will give a form that looks correct but will not pass all parameters. Let's say I have 3 recipes. And I set their quantities to 2,3,4 respectively and table_id to 1. When I check the parameters, I see that only the last recipe with its quantity was accepted. params[:order] => {"table_id"=>"1", "recipe"=>{"id"=>"4", "quantity"=>"4"}}
I need to be able to send all recipes with assigned quantities. Also, I am using the accepted answer in this question to be able to access the count column: Rails 4 Accessing the join table attributes
source to share
When you pass fields_for :recipes
multiple times, the method fields_for
doesn't know how you are sending the array of things. Therefore, it will specify the parameters as if it were only one instance, so only the last instance will get through. You have to pass an array of recipes in fields_for
so it can specify the parameters so that rails know it's an array of things when it's picked up again ( docs ). This is because form parameters in browsers do not support nesting by default. The actual parameters are flat key parameters. Rails has several naming conventions about how parameters can be named, so they will automatically be forced to be bound to an array.
<%= 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 %>
source to share