0


So i am trying to create an app that is basically a cookbook. My main model is the recipe and it has relation with 3 other models : ingredients, steps and baking. For the last one, it has to be a has_one/belongs_to relationship. My problem is that out of the threes models, only the two firsts (ingredients & steps) are showing up on the show page of the actual recipe after I submit the form.

Here is my recipe controller code:

class RecipesController < ApplicationController
  def index
    @recipes = Recipe.all
  end

  def show
    @recipe = Recipe.includes(:baking).find(params[:id])
  end

  def new
    @recipe = Recipe.new
  end

  def edit
    @recipe = Recipe.find(params[:id])
    @baking = @recipe.build_baking
  end

  def create
    @recipe = Recipe.new(recipe_params)
    @recipe.save

    if @recipe.save
      redirect_to recipe_path(@recipe)
    else
      render 'new'
    end
  end

  def update
    @recipe = Recipe.find(params[:id])
    @recipe.update(recipe_params)

    if @recipe.update(recipe_params)
      redirect_to recipe_path(@recipe)
    else
      render 'edit'
    end
  end

  def destroy
    @recipe = Recipe.find(params[:id])
    @recipe.destroy

    redirect_to root_path
  end

  private
  def recipe_params
    params.require(:recipe).permit(:recipe_name, :recipe_notes,
                                                ingredients_attributes: [:id, :ingredient_name, :quantity, :measuring,     :other, :optional, :_destroy],
                                                steps_attributes: [:id, :step_description, :step_notes, :_destroy],
                                                bakings_attributes: [:id, :no_baking, :baking_type, :heat, :unit, :duration, :baking_notes, :_destroy])
  end

end

Here are my models:

class Recipe < ApplicationRecord
  has_many :ingredients
  accepts_nested_attributes_for :ingredients

  has_many :steps
  accepts_nested_attributes_for :steps

  has_one :baking
  accepts_nested_attributes_for :baking
end

class Baking < ApplicationRecord
  belongs_to :recipe
end

My form :

<%= form_for @recipe do |f| %>

  <h4>Name</h4>
  <%= f.label :recipe_name %> <br>
  <%= f.text_field :recipe_name %>

  <h4>Ingredients</h4>
  <div id="ingredients">
    <%= f.fields_for :ingredients do |ingredient| %>
      <%= render 'ingredient_fields', :f => ingredient %>
    <% end %>
    <%= link_to_add_association 'add ingredient', f, :ingredients %>
  </div>

    <h4>Steps</h4>
    <div id="steps">
      <%= f.fields_for :steps do |step| %>
        <%= render 'step_fields', :f => step %>
      <% end %>
      <%= link_to_add_association 'add step', f, :steps %>
    </div>

    <h4>Baking</h4>
    <%= f.fields_for :bakings do |baking| %>
      <%= f.label :no_baking %> <br>
      <%= f.check_box :no_baking %>

      <%= f.label :baking_type %> <br>
      <%= f.text_field :baking_type %>

      <%= f.label :heat %> <br>
      <%= f.number_field :heat %>

      <%= f.label :unit %> <br>
      <%= f.text_field :unit %>

      <%= f.label :duration %> <br>
      <%= f.number_field :duration %>

      <%= f.label :baking_notes %> <br>
      <%= f.text_area :baking_notes %>

    <% end %>

  <%= f.submit 'Share Recipe' %>

<% end %>

And finally, here is what my show page looks like:

<h1><%= @recipe.recipe_name %></h1>

<h4>Ingredient list</h4>
<% @recipe.ingredients.each do |ingredient| %>
  <ul>
    <li><strong><%= ingredient.ingredient_name %></strong> <%= ingredient.quantity %> <%= ingredient.measuring %></li>
  </ul>
<% end %>

<h4>Steps</h4>
<% @recipe.steps.each do |step| %>
  <p><%= step.step_description %></p>
  <% if step.step_notes? %>
    <small><%= step.step_notes %></small>
  <% end %>
<% end %>

<h4>Baking</h4>
<% @recipe.baking do |baking| %>
<p>test</p>
  <ul>
    <li>Baking type: <%= baking.baking_type %></li>
    <li>Baking heat: <%= baking.heat %><%= @recipe.baking.unit %></li>
    <li>Cooking Time: <%= baking.duration %> minutes</li>
  </ul>
  <% if baking.baking_notes? %>
    <p><%= baking.baking_notes %></p>
  <% end %>
<% end %>

<p><%= @recipe.recipe_notes %></p>

I've been looking for several solutions, but since I don't get any error to guide me (the "baking" part just doesn't show up on the show page), I am kind of lost here. Any hints would be really appreciated :)

I'm really new to ruby so apologies if the question sounds stupid.

EDIT : changed bakings_attributes to baking_attributes in recipe_paramsand the baking part still doesn't show up.

Here are the logs when I submit the form:

Started POST "/recipes" for 127.0.0.1 at 2018-06-09 13:07:35 +1000
Processing by RecipesController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"7dMj/2UOUPgbZrx/e123kd2w1sVZCrfotyHdrrqAM2iNvfO4h0GGPOuYT00NqfTwzuiQtqmrXTEAuMxkY1bnFg==", "recipe"=>{"recipe_name"=>"pizza", "ingredients_attributes"=>{"1528513610918"=>{"ingredient_name"=>"Base", "quantity"=>"", "measuring"=>"", "other"=>"", "optional"=>"0", "_destroy"=>"false"}}, "steps_attributes"=>{"1528513616209"=>{"step_description"=>"Spread the base", "step_notes"=>"", "_destroy"=>"false"}}, "bakings"=>{"no_baking"=>"0", "baking_type"=>"Oven", "heat"=>"200", "unit"=>"C°", "duration"=>"20", "baking_notes"=>""}, "recipe_notes"=>""}, "commit"=>"Share Recipe"}
Unpermitted parameter: :bakings
   (0.3ms)  BEGIN
  SQL (0.5ms)  INSERT INTO "recipes" ("recipe_name", "recipe_notes", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id"  [["recipe_name", "pizza"], ["recipe_notes", ""], ["created_at", "2018-06-09 03:07:35.059515"], ["updated_at", "2018-06-09 03:07:35.059515"]]
  SQL (1.3ms)  INSERT INTO "ingredients" ("ingredient_name", "measuring", "other", "optional", "created_at", "updated_at", "recipe_id") VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING "id"  [["ingredient_name", "Base"], ["measuring", ""], ["other", ""], ["optional", "f"], ["created_at", "2018-06-09 03:07:35.061636"], ["updated_at", "2018-06-09 03:07:35.061636"], ["recipe_id", "26"]]
  SQL (0.4ms)  INSERT INTO "steps" ("step_description", "step_notes", "created_at", "updated_at", "recipe_id") VALUES ($1, $2, $3, $4, $5) RETURNING "id"  [["step_description", "Spread the base"], ["step_notes", ""], ["created_at", "2018-06-09 03:07:35.065734"], ["updated_at", "2018-06-09 03:07:35.065734"], ["recipe_id", "26"]]
   (148.7ms)  COMMIT
   (0.2ms)  BEGIN
   (0.2ms)  COMMIT
Redirected to http://localhost:3000/recipes/26
Completed 302 Found in 165ms (ActiveRecord: 151.5ms)


Started GET "/recipes/26" for 127.0.0.1 at 2018-06-09 13:07:35 +1000
Processing by RecipesController#show as HTML
  Parameters: {"id"=>"26"}
  Recipe Load (0.3ms)  SELECT  "recipes".* FROM "recipes" WHERE "recipes"."id" = $1 LIMIT $2  [["id", 26], ["LIMIT", 1]]
  Baking Load (0.3ms)  SELECT "bakings".* FROM "bakings" WHERE "bakings"."recipe_id" = 26
  Rendering recipes/show.html.erb within layouts/application
  Ingredient Load (0.2ms)  SELECT "ingredients".* FROM "ingredients" WHERE "ingredients"."recipe_id" = $1  [["recipe_id", "26"]]
  Step Load (0.2ms)  SELECT "steps".* FROM "steps" WHERE "steps"."recipe_id" = $1  [["recipe_id", "26"]]
  Rendered recipes/_crud-links.html.erb (1.0ms)
  Rendered recipes/show.html.erb within layouts/application (7.9ms)
Completed 200 OK in 41ms (Views: 33.4ms | ActiveRecord: 2.7ms)

The error that seems to cause the issue is : Unpermitted parameter: :bakingsso I tried to change the line in my form from <%= f.fields_for :bakings do |f| %>to <%= f.fields_for :baking do |f| %>but then the form for baking doesn't show up in the create view.
Any idea what could cause that?

EDIT :
I added the @recipe.build_bakingline in my def new method and whitelisted the baking attributes as follow:

private
 def recipe_params
  params.require(:recipe).permit(:recipe_name,
                                              :recipe_notes,
                                              :no_baking,
                                              :baking_type,
                                              :heat,
                                              :unit,
                                              :duration,
                                              :baking_notes,
                                              ingredients_attributes: [:id, :ingredient_name, :quantity, :measuring, :other, :optional, :_destroy],
                                              steps_attributes: [:id, :step_description, :step_notes, :_destroy])
end

The form still doesn't work.

2
  • It should be baking_attributes rather than bakings_attributes in recipe_params, since the relationship is singular. If it doens't work, post your server params log when you do the form submission. Commented Jun 9, 2018 at 2:47
  • Hey @kiddorails. Thanks for taking the time to reply.I just tried that and I get the error Unpermitted parameter: :bakingsin my logs. Also the form for baking doesn't show up in the create view anymore. All is detailed in the Edited part of my post. Commented Jun 9, 2018 at 3:24

1 Answer 1

1

Change your form to use form builder for baking rather than using parent form - Note ff below

<%= form_for @recipe do |f| %>

    <h4>Name</h4>
    <%= f.label :recipe_name %> <br>
    <%= f.text_field :recipe_name %>

    <h4>Ingredients</h4>
    <div id="ingredients">
      <%= f.fields_for :ingredients do |ingredient| %>
          <%= render 'ingredient_fields', :f => ingredient %>
      <% end %>
      <%= link_to_add_association 'add ingredient', f, :ingredients %>
    </div>

    <h4>Steps</h4>
    <div id="steps">
      <%= f.fields_for :steps do |step| %>
          <%= render 'step_fields', :f => step %>
      <% end %>
      <%= link_to_add_association 'add step', f, :steps %>
    </div>

    <h4>Baking</h4>
    <%= f.fields_for :baking do |ff| %>
        <%= ff.label :no_baking %> <br>
        <%= ff.check_box :no_baking %>

        <%= ff.label :baking_type %> <br>
        <%= ff.text_field :baking_type %>

        <%= ff.label :heat %> <br>
        <%= ff.number_field :heat %>

        <%= ff.label :unit %> <br>
        <%= ff.text_field :unit %>

        <%= ff.label :duration %> <br>
        <%= ff.number_field :duration %>

        <%= ff.label :baking_notes %> <br>
        <%= ff.text_area :baking_notes %>

    <% end %>

    <%= f.submit 'Share Recipe' %>

<% end %>

Change baking section of your show view to :

<h4>Baking</h4>
<% if baking = @recipe.baking %>
    <p>test</p>
    <ul>
      <li>Baking type: <%= baking.baking_type %></li>
      <li>Baking heat: <%= baking.heat %><%= @recipe.baking.unit %></li>
      <li>Cooking Time: <%= baking.duration %> minutes</li>
    </ul>
    <% if baking.baking_notes? %>
        <p><%= baking.baking_notes %></p>
    <% end %>
<% end %> 

In your controller, make sure you have whitelisted baking_attributes:

def recipe_params
    params.require(:recipe).permit(:recipe_name, :recipe_notes,
                                                ingredients_attributes: [:id, :ingredient_name, :quantity, :measuring,     :other, :optional, :_destroy],
                                                steps_attributes: [:id, :step_description, :step_notes, :_destroy],
                                                baking_attributes: [:id, :no_baking, :baking_type, :heat, :unit, :duration, :baking_notes, :_destroy])
  end
Sign up to request clarification or add additional context in comments.

6 Comments

I tried to change the form as you said but if I stick to the f.fields_for method, the form doesn't show up anymore in the new show page. Instead I used the form_formethod but when I try to submit it, nothing happen. Any idea what could be the issue here? What do you mean by whitelisting the baking_attributes?
@Moromain in def new method in controller, add the line at end @recipe.build_baking. By whitelisting baking_attributes, i meant having that in recipe_params instead of bakings_attributes
thanks again for your help. I just did that and the form still doesn't seems to be working (I edited my post). Any idea what else could cause that issue?
@Moromain adding build didn't show the fields in new page view?
also, you misinterpreted what i meant by baking_attributes. I edited my answer to show how recipe_params should be for the form to work.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.