Ruby on Rails : 嵌套属性不显示

Ruby on Rails : nested attribute doesn't show up


所以我正在尝试创建一个基本上是食谱的应用程序。 我的主要模型是食谱,它与其他 3 个模型有关系:配料、步骤和烘焙。 对于最后一个,它必须是 has_one/belongs_to 关系。 我的问题是,在我提交表格后,在三个模型中,只有两个第一次(成分和步骤)出现在实际食谱的显示页面上。

这是我的配方控制器代码:

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

这是我的模型:

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

我的表格:

<%= 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 %>

最后,这是我的展示页面的样子:

<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>

我一直在寻找几种解决方案,但由于我没有得到任何错误来指导我("baking" 部分只是没有出现在显示页面上),我有点迷失在这里。任何提示将不胜感激:)

我是 ruby 的新手,如果问题听起来很愚蠢,我深表歉意。

编辑:recipe_params 中将 bakings_attributes 更改为 baking_attributes,但烘焙部分仍然没有出现。

这是我提交表单时的日志:

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 (, , , ) 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 (, , , , , , ) 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 (, , , , ) 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" =  LIMIT   [["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" =   [["recipe_id", "26"]]
  Step Load (0.2ms)  SELECT "steps".* FROM "steps" WHERE "steps"."recipe_id" =   [["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)

似乎导致该问题的错误是:Unpermitted parameter: :bakings所以我尝试将表格中的行从 <%= f.fields_for :bakings do |f| %> 更改为 <%= f.fields_for :baking do |f| %> 但是烘焙表格没有' t 出现在创建视图中。
知道是什么原因造成的吗?

编辑:
我在我的 def 新方法中添加了 @recipe.build_baking 行,并将烘焙属性列入白名单,如下所示:

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

表单仍然无效。

更改您的表单以使用表单生成器进行烘焙而不是使用父表单 - 请注意下面的ff

<%= 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 %>

show 视图的 baking 部分更改为:

<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 %> 

在您的控制器中,确保您已列入白名单 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