简体   繁体   中英

Unpermitted parameter error in creating new model with has_many through association in Rails

I'm writing an Recipe app in Rails. Now I'm stuck in this error. I spent a week to find the solution for this problem.

Update model Here is my model:

class Recipe < ActiveRecord::Base
  has_many :ingredient_recipes
  has_many :ingredients, :through => :ingredient_recipes

  accepts_nested_attributes_for :ingredient_recipes
end

class Ingredient < ActiveRecord::Base
  has_many :ingredient_recipes
  has_many :recipes, :through => :ingredient_recipes
end

class IngredientRecipe < ActiveRecord::Base
  belongs_to :recipe
  belongs_to :ingredient
end

IngredientRecipe is a join model that is used to store the value of recipe and ingredient.

In 'New' action, I want to create new recipe along with the Ingredient for that recipe, and specify the quantity (quantity is an additional attribute in the join table IngredientRecipe) for that ingredient.

When I click submit, it just creates a new Recipe, it doesn't create a record in the Join table.

Here is my error:

Parameters: {"utf8"=>"✓", 
"authenticity_token"=>"AbnDeDLDWq3lvy4pozvXStVy7NeOIUuv1DU1U2/2EJ6n
 /jM6E1669hyB90733XTY9DGAvc2hbbDmbL6NwhqCUg==", 
"recipe"=>{"rec_name"=>"j", "rec_description"=>"k",
           "ingredient_recipe"=>{"ingredient"=>{"id"=>"1"},
           "quantity"=>"1"}}, "commit"=>"Create Recipe"}

Unpermitted parameter: ingredient_recipe 
(0.1ms)  BEGIN
  SQL (0.2ms)  INSERT INTO `recipes` (`rec_name`, `rec_description`, 
   `created_at`, `updated_at`) VALUES ('j', 'k', '2015-06-25 21:48:09', '2015-06-25 21:48:09')
 (1.1ms)  COMMIT  

Redirected to http://localhost:3000/recipes/50
Completed 302 Found in 6ms (ActiveRecord: 1.4ms)

Updated controller My recipe controller: Updated controller

    def new
    @recipe = Recipe.new
    3.times { @recipe.ingredient_recipes.build.build_ingredient }
  end
    def create
        @recipe = Recipe.new(recipe_params)
        respond_to do |format|
          if @recipe.save
            format.html { redirect_to @recipe, notice: 'Recipe was successfully created.' }
            format.json { render :show, status: :created, location: @recipe }
          else
            format.html { render :new }
            format.json { render json: @recipe.errors, status: :unprocessable_entity }
          end
    end
  end

My recipe view form:

    <%= form_for(@recipe) do |f| %>
  <% if @recipe.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@recipe.errors.count, "error") %> prohibited this recipe from being saved:</h2>
      <ul>
      <% @recipe.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :rec_name %><br>
    <%= f.text_field :rec_name %>
  </div>
  <div class="field">
    <%= f.label :rec_description %><br>
    <%= f.text_area :rec_description %>
  </div>
  <table>
    <thead>
      <tr>
        <th>Ingredients</th>
        <th>Unit</th>
        <th>Quantity</th>
        <th>New Quantity</th>
      </tr>
    </thead>
    <tbody>
      <%= f.fields_for :ingredient_recipes do |fi| %>
        <%= fi.fields_for do |i| %>
          <tr>
            <td> <%=i.collection_select(:ingredient_id, Ingredient.all, :id, :ing_name) %></td>
        <% end %>
            <td> <%=fi.text_field :quantity %></td>
          </tr>
      <% end %>
    </tbody>
  </table>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

No errors after I updated but here is the parameters what I get when I submit create action: Parameters: {"utf8"=>"✓", "authenticity_token"=>"NCT4NgS6ZvbqpcS4+CsoYI4pJurYzwsCyj5U6k3MTwSFqDpdLMX+XVFIpAP/pXD3ZDNr6T6mIOf58gUk6SEqOQ==", "recipe"=>{"rec_name"=>"s", "rec_description"=>"s", "ingredient_recipes_attributes"=>{"0"=>{"ingredient_id"=>"2", "quantity"=>"1"}, "1"=>{"ingredient_id"=>"1", "quantity"=>"1"}, "2"=>{"ingredient_id"=>"3", "quantity"=>"1"}}}, "commit"=>"Create Recipe"} (0.6ms) BEGIN SQL (4.6ms) INSERT INTO recipes ( created_at , updated_at ) VALUES ('2015-07-01 00:37:28', '2015-07-01 00:37:28') (2.1ms) COMMIT Redirected to http://localhost:3000/recipes/65 Completed 302 Found in 24ms (ActiveRecord: 7.3ms)

Started GET "/recipes/65" for 127.0.0.1 at 2015-06-30 17:37:28 -0700 Processing by RecipesController#show as HTML Parameters: {"id"=>"65"} Recipe Load (4.7ms) SELECT recipes .* FROM recipes WHERE recipes . id = 65 LIMIT 1 Rendered recipes/show.html.erb within layouts/application (0.7ms) Completed 200 OK in 136ms (Views: 126.4ms | ActiveRecord: 4.7ms)

It seems everything is on the right way but I don't know why after render show action It doesn't show the attributes of the recipe I just added, and It also didn't create the record in the join table.

Please help me! Thanks so much

You have an error in your model:

class Ingredient < ActiveRecord::Base
has_many :ingredient_recipes, inverse_of: :ingredient_recipes, autosave: true
has_many :recipes, :through => :ingredient_recipes

The following line is not correct. An inverse relationship to itself is not valid:

has_many :ingredient_recipes, inverse_of: :ingredient_recipes, autosave: true

This is why you're getting the error:

Unpermitted parameter: ingredient_recipe

Next steps (Added)

  • Remove the incorrect inverse_of relationship from the ingredient model
  • Evaluate whether you need an inverse_of relationship and what it should do
  • Only you know what your app needs to do, but if you need the original inverse_of ingredient_recipes, it should be here:
class IngredientRecipe < ActiveRecord::Base
  belongs_to :recipe, :inverse_of ingredient_recipes
  belongs_to :ingredient
  accepts_nested_attributes_for :ingredient
end

More debug advice: Remove "autosave" and create child record explicitly (Edit)

You must first create the parent record successfully before adding the "belongs to" child. Your autosave a parameter supposedly does this action, but it is not working for some reason, which you have to debug. To do this I suggest that you explicitly create an action on the child tables after you create your parent recipe record.

Once you get the parent and child records creating properly with explicit calls, then put the autosave back in the model, rollback the explicit creates and see if the parent save invokes the child save. I always use explicit saves because I want to control the process.


The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM