Mirv - Matt
Mirv - Matt

Reputation: 554

Rails 4 not taking parameter list - error in console - actionView::Template::error

Update: I had two issues in here - the one listed in the console had not matched the title I posted. The issue with actionView::Template::error was in fact caused by the lack of pluralization - I gave answer for it to the most complete answer below - thank you!

Original Question:

I'm working with cocoon gemfile & following the ERB style of it without haml/slim. I have my github here - The branch I'm working on is "cmodel" -Link. I got one of the errors taken care of myself - but this last one is just elusive - oddly too - I lost the field that normally shows the ingredient with the quantity - back on to the point...

My question is ... since when I search my repo on github for "ingredient_attributes" & see it only in my controller parameter's ... where is the error coming from & what would fix it?

"Unpermitted parameter: ingredient_attributes"

or

"Unpermitted parameter: ingredients" is coming from ... I managed to get this mostly working - this is the last element and I've been over a ton of files and stated pluralization etc, along with trying 3 or 4 formats for the accept_parameters_for & then the ingredient_attributes.

My console output for the current error:

Started GET "/recipes/1/edit" for 68.54.21.200 at 2015-12-21 02:53:27 +0000
Cannot render console from 68.54.21.200! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by RecipesController#edit as HTML
  Parameters: {"id"=>"1"}
  Recipe Load (0.2ms)  SELECT  "recipes".* FROM "recipes" WHERE "recipes"."id" = ? LIMIT 1  [["id", 1]]
  CACHE (0.0ms)  SELECT  "recipes".* FROM "recipes" WHERE "recipes"."id" = ? LIMIT 1  [["id", "1"]]
  Rendered recipes/_form.html.erb (8.2ms)
  Rendered recipes/edit.html.erb within layouts/application (9.8ms)
Completed 500 Internal Server Error in 16ms (ActiveRecord: 0.3ms)

ActionView::Template::Error (No association found for name `ingredients'. Has it been defined yet?):
    30: 
    31:   <fieldset id="recipe-ingredients">
    32:     <ol>
    33:       <%= f.fields_for :quantities do |quantity| %>
    34:         <%= render 'quantity_fields', f: quantity %>
    35:       <% end %>
    36:     </ol>
  app/models/quantity.rb:6:in `<class:Quantity>'
  app/models/quantity.rb:1:in `<top (required)>'
  app/views/recipes/_form.html.erb:33:in `block in _app_views_recipes__form_html_erb___1490943344300843366_36721460'
  app/views/recipes/_form.html.erb:1:in `_app_views_recipes__form_html_erb___1490943344300843366_36721460'
  app/views/recipes/edit.html.erb:3:in `_app_views_recipes_edit_html_erb___3608590124593016081_36957880'


  Rendered /usr/local/rvm/gems/ruby-2.2.1/gems/actionpack-4.2.4/lib/action_dispatch/middleware/templates/rescues/_source.erb (20.7ms)
  Rendered /usr/local/rvm/gems/ruby-2.2.1/gems/actionpack-4.2.4/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (5.1ms)
  Rendered /usr/local/rvm/gems/ruby-2.2.1/gems/actionpack-4.2.4/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (3.6ms)
  Rendered /usr/local/rvm/gems/ruby-2.2.1/gems/actionpack-4.2.4/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb within rescues/layout (99.4ms)

Setup

Models:

class Recipe < ActiveRecord::Base
  has_many :quantities
  has_many :ingredient,
           :through => :quantities
  accepts_nested_attributes_for :quantities,
           :allow_destroy => true
  accepts_nested_attributes_for :ingredient
end

class Quantity < ActiveRecord::Base
  belongs_to :recipe
  belongs_to :ingredient
  accepts_nested_attributes_for :ingredient
end

class Ingredient < ActiveRecord::Base
  has_many :quantities
  has_many :recipes, through: :quantities
  accepts_nested_attributes_for :quantities
end

Controller:

class RecipesController < ApplicationController
  before_action :set_recipe, only: [:show, :edit, :update, :destroy]


  # GET /recipes/1/edit
  def edit
        @recipe = Recipe.find(params[:id])
  end

  # POST /recipes
  # POST /recipes.json
  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

  # PATCH/PUT /recipes/1
  # PATCH/PUT /recipes/1.json
  def update
    respond_to do |format|
      if @recipe.update(recipe_params)
        format.html { redirect_to @recipe, notice: 'Recipe was successfully updated.' }
        format.json { render :show, status: :ok, location: @recipe }
      else
        format.html { render :edit }
        format.json { render json: @recipe.errors, status: :unprocessable_entity }
      end
    end
  end


  private
    # Use callbacks to share common setup or constraints between actions.
    def set_recipe
      @recipe = Recipe.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def recipe_params
      #seems to work, but getting errors saving
      params.require(:recipe).permit(:title, :description, :instruction, 
      quantities_attributes:  [:id, :amount, :ingredient, :_destroy], 
      ingredient_attributes:  [:id, :name, :_destroy],
      recipe_attributes:      [:title, :description, :_destroy])
    end
end

Here's the views ... portion from the github I linked above ...

edit.html.erb

<h1>Editing Recipe</h1>

    <%= render 'form' %>

    <%= link_to 'Show', @recipe %> |
    <%= link_to 'Back', recipes_path %>

_form.html.erb

<%= form_for @recipe, html: {class: "form-horizontal"} 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 %>

  <fieldset id="recipe-meta">
    <ol>
      <li class="control-group">
        <%= f.label :title, "Recipe Name", class: "control-label" %>
        <div class="controls"><%= f.text_field :title %></div>
      </li>
      <li class="control-group">
        <%= f.label :description, "A brief description of this recipe", class: "control-label" %>
        <div class="controls"><%= f.text_area :description, rows: 5 %></div>
      </li>
      <li class="control-group">
        <%= f.label :instruction, "Instructions for this recipe", class: "control-label" %>
        <div class="controls"><%= f.text_area :instruction, rows: 10 %></div>
      </li>
    </ol>
  </fieldset>

  <fieldset id="recipe-ingredients">
    <ol>
      <%= f.fields_for :quantities do |quantity| %>
        <%= render 'quantity_fields', f: quantity %>
      <% end %>
    </ol>
    <%= link_to_add_association 'add ingredient', f, :quantities, 'data-association-insertion-node' => "#recipe-ingredients ol", 'data-association-insertion-method' => "append", :wrap_object => Proc.new {|quantity| quantity.build_ingredient; quantity } %>
  </fieldset>
    <%= f.submit %>
  </div>
<% end %>

_quantity_fields.html.erb

<li class="control-group nested-fields">
  <div class="controls">
    <%= f.label :amount, "Amount:" %>
    <%= f.text_field :amount %>

    <%= f.fields_for :ingredient do |quantity_ingredient| %>
      <%= quantity_ingredient.text_field :name %>
    <% end %>

    <%= link_to_remove_association "remove", f %>
  </div>
</li>

Upvotes: 0

Views: 125

Answers (2)

Richard Peck
Richard Peck

Reputation: 76774

As an addition to Praveen George's answer, you can debug Rails relatively simply if you follow what it says on screen (most of the time):

No association found for name `ingredients'. Has it been defined yet?

This basically means that you don't have the ingredients association defined in the model you're calling.

As pointed out by Praveen, your problem resides in the Recipe model. You have to call the association by its pluralized name:

#app/models/recipe.rb
class Recipe < ActiveRecord::Base
   has_many :ingredients
   accepts_nested_attributes_for :ingredients
end

Upvotes: 2

Praveen George
Praveen George

Reputation: 9715

There is an error in declaring association class Recipe with has_many relation. try changing the relation to the following in your Recipe model

has_many :ingredients

Upvotes: 2

Related Questions