Ruby on Rails:嵌套属性未显示

时间:2018-06-09 02:16:17

标签: ruby-on-rails ruby model-view-controller model nested-forms


所以我想创建一个基本上是一本食谱的应用程序。 我的主要模型是食谱,它与其他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>

我一直在寻找几种解决方案,但由于我没有任何错误来指导我(“烘焙”部分没有出现在展会页面上),我有点迷失在这里。任何提示都会非常感激:)

我真的对ruby不熟悉,如果这个问题听起来很愚蠢,那么道歉。

编辑:bakings_attributes更改为baking_attributes中的recipe_params,但烘焙部分仍未显示。

以下是我提交表单时的日志:

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)

似乎导致此问题的错误是:Unpermitted parameter: :bakings因此我尝试将表单中的行从<%= f.fields_for :bakings do |f| %>更改为<%= f.fields_for :baking do |f| %>,但之后烘焙表单未显示在创建视图中。
知道是什么原因引起的吗?

编辑:
我在def new方法中添加了@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

表单仍无效。

1 个答案:

答案 0 :(得分:1)

更改表单以使用表单构建器进行烘焙而不是使用父表单 - 请注意下面的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视图的烘焙部分更改为:

<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