【问题标题】:Ruby on Rails : nested attribute doesn't show upRuby on Rails:嵌套属性不显示
【发布时间】:2018-11-19 02:05:01
【问题描述】:


所以我正在尝试创建一个基本上是一本食谱的应用程序。 我的主要模型是配方,它与其他 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​​ 真的很陌生,如果这个问题听起来很愚蠢,我深表歉意。

编辑: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 ($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所以我尝试将表单中的行从&lt;%= f.fields_for :bakings do |f| %&gt;更改为&lt;%= f.fields_for :baking do |f| %&gt;,但随后烘焙表单没有显示在创建视图中。
知道是什么原因造成的吗?

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

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

表格还是不行。

【问题讨论】:

  • 它应该是baking_attributes 而不是recipe_params 中的bakings_attributes,因为关系是单数的。如果它不起作用,请在提交表单时发布您的服务器 params 日志。
  • 嘿@kiddorails。感谢您花时间回复。我刚刚尝试过,我在日志中收到错误Unpermitted parameter: :bakings。此外,烘焙表单不再显示在创建视图中。所有内容都在我帖子的已编辑部分详细说明。

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


【解决方案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

【讨论】:

  • 我尝试按照您所说的更改表单,但如果我坚持使用f.fields_for 方法,则表单不会再出现在新的显示页面中。相反,我使用了form_formethod,但是当我尝试提交它时,什么也没有发生。知道这里可能是什么问题吗?将baking_attributes 列入白名单是什么意思?
  • @Moromain 在控制器中的def new 方法中,在末尾添加行@recipe.build_baking。通过将 baking_attributes 列入白名单,我的意思是在 recipe_params 中而不是 bakings_attributes
  • 再次感谢您的帮助。我只是这样做了,表格似乎仍然不起作用(我编辑了我的帖子)。知道还有什么可能导致这个问题吗?
  • @Moromain 添加build 没有显示new 页面视图中的字段?
  • 另外,你误解了我所说的 bake_attributes 的意思。我编辑了我的答案以显示recipe_params 应该如何使表单工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-25
  • 2014-02-05
  • 1970-01-01
  • 2014-04-03
相关资源
最近更新 更多