Ruby on Rails 4:提交后缺少表单字段 - 错误是 "Unpermitted parameter: ingredients_attributes"
Ruby on Rails 4: Missing form field after commit - error is "Unpermitted parameter: ingredients_attributes"
问题:
我正在使用 cocoon gemfile 并在没有 haml/slim 的情况下遵循它的 ERB 风格。我这里有我的 github - 我正在处理的 b运行ch 是 "cmodel" - Link。
错误是:不允许的参数:ingredient_attributes
真的,我不明白的是关于模型的一切。我明白多元化是一回事。我知道强参数是一回事。我对实施它们的理解有点模糊。我发现 rails guides 和 edge rails guides 对于此处的扩展使用来说太简单了。我已经进行了 80 多次更改,感觉我的安装完全失败了。
我做了一些额外的事情:
- 在试图猜测问题的模型中盲目地添加过多 accepts_attributes_for
我添加了一个非复数的强参数来尝试找出是否是这个问题
在 quantities_attributes 中添加了成分 - 盲目希望就是这样
删除了所有成分_属性
我现在有一个奇怪的模式,将东西放入数据库可能不应该
从允许的强参数列表中提取成分和数量。然后添加到 quantities_attributes - 没有问题。然后尝试对 ingredient(s)_attributes 进行同样的操作...问题仍然存在。
更新 @ 08:29pm - 12/25/15:
奇怪的副作用... 15 或 20 次测试前,当您单击添加成分时我注意到第二个字段 link 可以添加,但是当您单击编辑时第二列不显示。可能相关?
总而言之,我想这一切都应该有效——它与其他人使用的另一个示例相匹配,根据示例,它没有理由失败。
该代码对强参数区域中的复数完全没有反应 - 令人沮丧。我觉得我的开发方法现在很无聊,在这个垃圾4小时后休息一下。
当前错误的控制台输出:已更新@08:29pm - 12/25/15
Started PATCH "/recipes/1" for 68.54.21.200 at 2015-12-26 03:00:14 +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#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"OzJmuRuIMWVbJ1CpnCTyU52GhTEmrsOfiBiHACzIviN02MO48HBaZlX8JKvZvBXErqBfbXULnhcjT3gk2Zrh+A==", "recipe"=>{"title"=>"Recipe name", "description"=>"Recipe Description of Lindy's ...", "instruction"=>"Recipe Instruction", "quantities_attributes"=>{"0"=>{"amount"=>"8", "_destroy"=>"false", "id"=>"63"}, "1"=>{"amount"=>"9", "_destroy"=>"false", "id"=>"64"}, "1451098805028"=>{"amount"=>"11", "ingredient_attributes"=>{"name"=>"11"}, "_destroy"=>"false"}}}, "commit"=>"Update Recipe", "id"=>"1"}
Recipe Load (0.2ms) SELECT "recipes".* FROM "recipes" WHERE "recipes"."id" = ? LIMIT 1 [["id", 1]]
Unpermitted parameter: ingredient_attributes
(0.1ms) begin transaction
Quantity Load (0.3ms) SELECT "quantities".* FROM "quantities" WHERE "quantities"."recipe_id" = ? AND "quantities"."id" IN (63, 64) [["recipe_id", "1"]]
SQL (0.4ms) INSERT INTO "quantities" ("amount", "recipe_id", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["amount", 11], ["recipe_id", "1"], ["created_at", "2015-12-26 03:00:14.818224"], ["updated_at", "2015-12-26 03:00:14.818224"]]
(9.6ms) commit transaction
Redirected to https://cocoontest-mirv.c9users.io/recipes/1
Completed 302 Found in 19ms (ActiveRecord: 10.7ms)
设置
- 我运行 gemfile 的捆绑包安装。
- 我在 assests/application.js 中输入了“//= require cocoon”。它已经过编译和整理。
- 我设置了一个控制器来直接查看配料模型,并可以通过配料页面手动添加它们 - 但它从不通过配方模型保存我的配料。
型号:
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
控制器:更新 @ 08:29pm - 12/25/15
class RecipesController < ApplicationController
before_action :set_recipe, only: [:show, :edit, :update, :destroy]
# GET /recipes
# GET /recipes.json
def index
@recipes = Recipe.all
end
# GET /recipes/1
# GET /recipes/1.json
def show
@recipe = Recipe.find(params[:id])
end
# GET /recipes/new
def new
@recipe = Recipe.new
end
# 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
# DELETE /recipes/1
# DELETE /recipes/1.json
def destroy
@recipe.destroy
respond_to do |format|
format.html { redirect_to recipes_url, notice: 'Recipe was successfully destroyed.' }
format.json { head :no_content }
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 used wrong pluralization for quantity, should have been quantities_attributes
params.require(:recipe).permit(:title, :description, :instruction,
:quantities_attributes => [:id, :ingredient, :ingredient_id, :recipe_id, :amount, :_destroy],
:ingredient_attributes => [:id, :_destroy, :ingredient_id, :name],
:ingredients_attributes => [:id, :_destroy, :ingredient_id, :name]
)
end
end
这是观点...来自 github 我在上面 linked 的部分...
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>
架构
ActiveRecord::Schema.define(version: 20151206204139) do
create_table "ingredients", force: :cascade do |t|
t.text "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "ingredient_id"
end
create_table "quantities", force: :cascade do |t|
t.integer "amount"
t.text "ingredient"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "recipe_id"
t.integer "ingredient_id"
end
add_index "quantities", ["recipe_id"], name: "index_quantities_on_recipe_id"
create_table "recipes", force: :cascade do |t|
t.string "title"
t.text "description"
t.text "instruction"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "recipe_id"
end
add_index "recipes", ["recipe_id"], name: "index_recipes_on_recipe_id"
end
更新:包括查看编辑页面的源代码...这是目前为止项目产生的html页面...
<!DOCTYPE html>
<html>
<head>
<title>Workspace</title>
<link rel="stylesheet" media="all" href="/assets/ingredients.self-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.css?body=1" data-turbolinks-track="true" />
<link rel="stylesheet" media="all" href="/assets/quantities.self-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.css?body=1" data-turbolinks-track="true" />
<link rel="stylesheet" media="all" href="/assets/recipes.self-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.css?body=1" data-turbolinks-track="true" />
<link rel="stylesheet" media="all" href="/assets/scaffolds.self-d2e5ccad1506299feea3a35bfb7c525e101bb3b214303715deb675fdc539948b.css?body=1" data-turbolinks-track="true" />
<link rel="stylesheet" media="all" href="/assets/application.self-e80e8f2318043e8af94dddc2adad5a4f09739a8ebb323b3ab31cd71d45fd9113.css?body=1" data-turbolinks-track="true" />
<script src="/assets/jquery.self-a714331225dda820228db323939889f149aec0127aeb06255646b616ba1ca419.js?body=1" data-turbolinks-track="true"></script>
<script src="/assets/jquery_ujs.self-d456baa54c1fa6be2ec3711f0a72ddf7a5b2f34a6b4f515f33767d6207b7d4b3.js?body=1" data-turbolinks-track="true"></script>
<script src="/assets/turbolinks.self-c37727e9bd6b2735da5c311aa83fead54ed0be6cc8bd9a65309e9c5abe2cbfff.js?body=1" data-turbolinks-track="true"></script>
<script src="/assets/ingredients.self-877aef30ae1b040ab8a3aba4e3e309a11d7f2612f44dde450b5c157aa5f95c05.js?body=1" data-turbolinks-track="true"></script>
<script src="/assets/quantities.self-877aef30ae1b040ab8a3aba4e3e309a11d7f2612f44dde450b5c157aa5f95c05.js?body=1" data-turbolinks-track="true"></script>
<script src="/assets/recipes.self-877aef30ae1b040ab8a3aba4e3e309a11d7f2612f44dde450b5c157aa5f95c05.js?body=1" data-turbolinks-track="true"></script>
<script src="/assets/cocoon.self-05633fd25797688a657c08b26b8d4217031ee589f5ca76f0a57c11ac7d0e76ec.js?body=1" data-turbolinks-track="true"></script>
<script src="/assets/application.self-7862a8a8b42407b4741a1adeeea35f0d13ddc4f702ec532adb0674491d296495.js?body=1" data-turbolinks-track="true"></script>
<meta name="csrf-param" content="authenticity_token" />
<meta name="csrf-token" content="Yco8LpQtKNyieVhjN1HKDzyMMyMfVHJ+UpllUl7iR88uIJkvf9VD36yiLGFyyS2YD6rpf0zxL/b5zpp2q7AYFA==" />
</head>
<body>
<h1>Editing Recipe</h1>
<form class="form-horizontal" id="edit_recipe_2" action="/recipes/2" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="✓" /><input type="hidden" name="_method" value="patch" /><input type="hidden" name="authenticity_token" value="DxvtQX6V7LtVoez4faEXT5L/t2vOORoprujYH4IXqJFA8UhAlW2HuFt6mPo4OfDYodltN52cR6EFvyc7d0X3Sg==" />
<fieldset id="recipe-meta">
<ol>
<li class="control-group">
<label class="control-label" for="recipe_title">Recipe Name</label>
<div class="controls"><input type="text" value="Test2" name="recipe[title]" id="recipe_title" /></div>
</li>
<li class="control-group">
<label class="control-label" for="recipe_description">A brief description of this recipe</label>
<div class="controls"><textarea rows="5" name="recipe[description]" id="recipe_description">
Test2</textarea></div>
</li>
<li class="control-group">
<label class="control-label" for="recipe_instruction">Instructions for this recipe</label>
<div class="controls"><textarea rows="10" name="recipe[instruction]" id="recipe_instruction">
Test2</textarea></div>
</li>
</ol>
</fieldset>
<fieldset id="recipe-ingredients">
<ol>
<li class="control-group nested-fields">
<div class="controls">
<label for="recipe_quantities_attributes_0_amount">Amount:</label>
<input type="text" value="111" name="recipe[quantities_attributes][0][amount]" id="recipe_quantities_attributes_0_amount" />
<input type="hidden" name="recipe[quantities_attributes][0][_destroy]" id="recipe_quantities_attributes_0__destroy" value="false" /><a class="remove_fields existing" href="#">remove</a>
</div>
</li>
<input type="hidden" value="38" name="recipe[quantities_attributes][0][id]" id="recipe_quantities_attributes_0_id" />
<li class="control-group nested-fields">
<div class="controls">
<label for="recipe_quantities_attributes_1_amount">Amount:</label>
<input type="text" value="111" name="recipe[quantities_attributes][1][amount]" id="recipe_quantities_attributes_1_amount" />
<input type="hidden" name="recipe[quantities_attributes][1][_destroy]" id="recipe_quantities_attributes_1__destroy" value="false" /><a class="remove_fields existing" href="#">remove</a>
</div>
</li>
<input type="hidden" value="39" name="recipe[quantities_attributes][1][id]" id="recipe_quantities_attributes_1_id" />
<li class="control-group nested-fields">
<div class="controls">
<label for="recipe_quantities_attributes_2_amount">Amount:</label>
<input type="text" value="1111" name="recipe[quantities_attributes][2][amount]" id="recipe_quantities_attributes_2_amount" />
<input type="hidden" name="recipe[quantities_attributes][2][_destroy]" id="recipe_quantities_attributes_2__destroy" value="false" /><a class="remove_fields existing" href="#">remove</a>
</div>
</li>
<input type="hidden" value="40" name="recipe[quantities_attributes][2][id]" id="recipe_quantities_attributes_2_id" />
<li class="control-group nested-fields">
<div class="controls">
<label for="recipe_quantities_attributes_3_amount">Amount:</label>
<input type="text" value="2222" name="recipe[quantities_attributes][3][amount]" id="recipe_quantities_attributes_3_amount" />
<input type="hidden" name="recipe[quantities_attributes][3][_destroy]" id="recipe_quantities_attributes_3__destroy" value="false" /><a class="remove_fields existing" href="#">remove</a>
</div>
</li>
<input type="hidden" value="41" name="recipe[quantities_attributes][3][id]" id="recipe_quantities_attributes_3_id" />
<li class="control-group nested-fields">
<div class="controls">
<label for="recipe_quantities_attributes_4_amount">Amount:</label>
<input type="text" value="33" name="recipe[quantities_attributes][4][amount]" id="recipe_quantities_attributes_4_amount" />
<input type="hidden" name="recipe[quantities_attributes][4][_destroy]" id="recipe_quantities_attributes_4__destroy" value="false" /><a class="remove_fields existing" href="#">remove</a>
</div>
</li>
<input type="hidden" value="42" name="recipe[quantities_attributes][4][id]" id="recipe_quantities_attributes_4_id" />
<li class="control-group nested-fields">
<div class="controls">
<label for="recipe_quantities_attributes_5_amount">Amount:</label>
<input type="text" value="444" name="recipe[quantities_attributes][5][amount]" id="recipe_quantities_attributes_5_amount" />
<input type="hidden" name="recipe[quantities_attributes][5][_destroy]" id="recipe_quantities_attributes_5__destroy" value="false" /><a class="remove_fields existing" href="#">remove</a>
</div>
</li>
<input type="hidden" value="43" name="recipe[quantities_attributes][5][id]" id="recipe_quantities_attributes_5_id" /> </ol>
<a data-association-insertion-node="#recipe-ingredients ol" data-association-insertion-method="append" class="add_fields" data-association="quantity" data-associations="quantities" data-association-insertion-template="<li class="control-group nested-fields">
<div class="controls">
<label for="recipe_quantities_attributes_new_quantities_amount">Amount:</label>
<input type="text" name="recipe[quantities_attributes][new_quantities][amount]" id="recipe_quantities_attributes_new_quantities_amount" />
<input type="text" name="recipe[quantities_attributes][new_quantities][ingredient_attributes][name]" id="recipe_quantities_attributes_new_quantities_ingredient_attributes_name" />
<input type="hidden" name="recipe[quantities_attributes][new_quantities][_destroy]" id="recipe_quantities_attributes_new_quantities__destroy" value="false" /><a class="remove_fields dynamic" href="#">remove</a>
</div>
</li>" href="#">add ingredient</a>
</fieldset>
<input type="submit" name="commit" value="Update Recipe" />
</div>
</form>
<a href="/recipes/2">Show</a> |
<a href="/recipes">Back</a>
</body>
</html>
您的 recipe_params
方法需要更改 - 您的表单中实际上有两层嵌套(配方 -> 数量 -> 成分),因此您的参数许可需要反映这一点。
在您的方法中,删除 ingredient_attributes
和 ingredients_attributes
部分 - 它们与您提交的参数的格式不匹配。相反,您需要如下内容:
:quantities_attributes => [:id, :ingredient, :ingredient_id, :recipe_id, :amount,
:_destroy, :ingredient_attributes => [:id, :_destroy, :ingredient_id, :name]]
问题:
我正在使用 cocoon gemfile 并在没有 haml/slim 的情况下遵循它的 ERB 风格。我这里有我的 github - 我正在处理的 b运行ch 是 "cmodel" - Link。
错误是:不允许的参数:ingredient_attributes
真的,我不明白的是关于模型的一切。我明白多元化是一回事。我知道强参数是一回事。我对实施它们的理解有点模糊。我发现 rails guides 和 edge rails guides 对于此处的扩展使用来说太简单了。我已经进行了 80 多次更改,感觉我的安装完全失败了。
我做了一些额外的事情:
- 在试图猜测问题的模型中盲目地添加过多 accepts_attributes_for
我添加了一个非复数的强参数来尝试找出是否是这个问题
在 quantities_attributes 中添加了成分 - 盲目希望就是这样
删除了所有成分_属性
我现在有一个奇怪的模式,将东西放入数据库可能不应该
从允许的强参数列表中提取成分和数量。然后添加到 quantities_attributes - 没有问题。然后尝试对 ingredient(s)_attributes 进行同样的操作...问题仍然存在。
更新 @ 08:29pm - 12/25/15:
奇怪的副作用... 15 或 20 次测试前,当您单击添加成分时我注意到第二个字段 link 可以添加,但是当您单击编辑时第二列不显示。可能相关?
总而言之,我想这一切都应该有效——它与其他人使用的另一个示例相匹配,根据示例,它没有理由失败。
该代码对强参数区域中的复数完全没有反应 - 令人沮丧。我觉得我的开发方法现在很无聊,在这个垃圾4小时后休息一下。
当前错误的控制台输出:已更新@08:29pm - 12/25/15
Started PATCH "/recipes/1" for 68.54.21.200 at 2015-12-26 03:00:14 +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#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"OzJmuRuIMWVbJ1CpnCTyU52GhTEmrsOfiBiHACzIviN02MO48HBaZlX8JKvZvBXErqBfbXULnhcjT3gk2Zrh+A==", "recipe"=>{"title"=>"Recipe name", "description"=>"Recipe Description of Lindy's ...", "instruction"=>"Recipe Instruction", "quantities_attributes"=>{"0"=>{"amount"=>"8", "_destroy"=>"false", "id"=>"63"}, "1"=>{"amount"=>"9", "_destroy"=>"false", "id"=>"64"}, "1451098805028"=>{"amount"=>"11", "ingredient_attributes"=>{"name"=>"11"}, "_destroy"=>"false"}}}, "commit"=>"Update Recipe", "id"=>"1"}
Recipe Load (0.2ms) SELECT "recipes".* FROM "recipes" WHERE "recipes"."id" = ? LIMIT 1 [["id", 1]]
Unpermitted parameter: ingredient_attributes
(0.1ms) begin transaction
Quantity Load (0.3ms) SELECT "quantities".* FROM "quantities" WHERE "quantities"."recipe_id" = ? AND "quantities"."id" IN (63, 64) [["recipe_id", "1"]]
SQL (0.4ms) INSERT INTO "quantities" ("amount", "recipe_id", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["amount", 11], ["recipe_id", "1"], ["created_at", "2015-12-26 03:00:14.818224"], ["updated_at", "2015-12-26 03:00:14.818224"]]
(9.6ms) commit transaction
Redirected to https://cocoontest-mirv.c9users.io/recipes/1
Completed 302 Found in 19ms (ActiveRecord: 10.7ms)
设置
- 我运行 gemfile 的捆绑包安装。
- 我在 assests/application.js 中输入了“//= require cocoon”。它已经过编译和整理。
- 我设置了一个控制器来直接查看配料模型,并可以通过配料页面手动添加它们 - 但它从不通过配方模型保存我的配料。
型号:
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
控制器:更新 @ 08:29pm - 12/25/15
class RecipesController < ApplicationController
before_action :set_recipe, only: [:show, :edit, :update, :destroy]
# GET /recipes
# GET /recipes.json
def index
@recipes = Recipe.all
end
# GET /recipes/1
# GET /recipes/1.json
def show
@recipe = Recipe.find(params[:id])
end
# GET /recipes/new
def new
@recipe = Recipe.new
end
# 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
# DELETE /recipes/1
# DELETE /recipes/1.json
def destroy
@recipe.destroy
respond_to do |format|
format.html { redirect_to recipes_url, notice: 'Recipe was successfully destroyed.' }
format.json { head :no_content }
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 used wrong pluralization for quantity, should have been quantities_attributes
params.require(:recipe).permit(:title, :description, :instruction,
:quantities_attributes => [:id, :ingredient, :ingredient_id, :recipe_id, :amount, :_destroy],
:ingredient_attributes => [:id, :_destroy, :ingredient_id, :name],
:ingredients_attributes => [:id, :_destroy, :ingredient_id, :name]
)
end
end
这是观点...来自 github 我在上面 linked 的部分...
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>
架构
ActiveRecord::Schema.define(version: 20151206204139) do
create_table "ingredients", force: :cascade do |t|
t.text "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "ingredient_id"
end
create_table "quantities", force: :cascade do |t|
t.integer "amount"
t.text "ingredient"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "recipe_id"
t.integer "ingredient_id"
end
add_index "quantities", ["recipe_id"], name: "index_quantities_on_recipe_id"
create_table "recipes", force: :cascade do |t|
t.string "title"
t.text "description"
t.text "instruction"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "recipe_id"
end
add_index "recipes", ["recipe_id"], name: "index_recipes_on_recipe_id"
end
更新:包括查看编辑页面的源代码...这是目前为止项目产生的html页面...
<!DOCTYPE html>
<html>
<head>
<title>Workspace</title>
<link rel="stylesheet" media="all" href="/assets/ingredients.self-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.css?body=1" data-turbolinks-track="true" />
<link rel="stylesheet" media="all" href="/assets/quantities.self-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.css?body=1" data-turbolinks-track="true" />
<link rel="stylesheet" media="all" href="/assets/recipes.self-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.css?body=1" data-turbolinks-track="true" />
<link rel="stylesheet" media="all" href="/assets/scaffolds.self-d2e5ccad1506299feea3a35bfb7c525e101bb3b214303715deb675fdc539948b.css?body=1" data-turbolinks-track="true" />
<link rel="stylesheet" media="all" href="/assets/application.self-e80e8f2318043e8af94dddc2adad5a4f09739a8ebb323b3ab31cd71d45fd9113.css?body=1" data-turbolinks-track="true" />
<script src="/assets/jquery.self-a714331225dda820228db323939889f149aec0127aeb06255646b616ba1ca419.js?body=1" data-turbolinks-track="true"></script>
<script src="/assets/jquery_ujs.self-d456baa54c1fa6be2ec3711f0a72ddf7a5b2f34a6b4f515f33767d6207b7d4b3.js?body=1" data-turbolinks-track="true"></script>
<script src="/assets/turbolinks.self-c37727e9bd6b2735da5c311aa83fead54ed0be6cc8bd9a65309e9c5abe2cbfff.js?body=1" data-turbolinks-track="true"></script>
<script src="/assets/ingredients.self-877aef30ae1b040ab8a3aba4e3e309a11d7f2612f44dde450b5c157aa5f95c05.js?body=1" data-turbolinks-track="true"></script>
<script src="/assets/quantities.self-877aef30ae1b040ab8a3aba4e3e309a11d7f2612f44dde450b5c157aa5f95c05.js?body=1" data-turbolinks-track="true"></script>
<script src="/assets/recipes.self-877aef30ae1b040ab8a3aba4e3e309a11d7f2612f44dde450b5c157aa5f95c05.js?body=1" data-turbolinks-track="true"></script>
<script src="/assets/cocoon.self-05633fd25797688a657c08b26b8d4217031ee589f5ca76f0a57c11ac7d0e76ec.js?body=1" data-turbolinks-track="true"></script>
<script src="/assets/application.self-7862a8a8b42407b4741a1adeeea35f0d13ddc4f702ec532adb0674491d296495.js?body=1" data-turbolinks-track="true"></script>
<meta name="csrf-param" content="authenticity_token" />
<meta name="csrf-token" content="Yco8LpQtKNyieVhjN1HKDzyMMyMfVHJ+UpllUl7iR88uIJkvf9VD36yiLGFyyS2YD6rpf0zxL/b5zpp2q7AYFA==" />
</head>
<body>
<h1>Editing Recipe</h1>
<form class="form-horizontal" id="edit_recipe_2" action="/recipes/2" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="✓" /><input type="hidden" name="_method" value="patch" /><input type="hidden" name="authenticity_token" value="DxvtQX6V7LtVoez4faEXT5L/t2vOORoprujYH4IXqJFA8UhAlW2HuFt6mPo4OfDYodltN52cR6EFvyc7d0X3Sg==" />
<fieldset id="recipe-meta">
<ol>
<li class="control-group">
<label class="control-label" for="recipe_title">Recipe Name</label>
<div class="controls"><input type="text" value="Test2" name="recipe[title]" id="recipe_title" /></div>
</li>
<li class="control-group">
<label class="control-label" for="recipe_description">A brief description of this recipe</label>
<div class="controls"><textarea rows="5" name="recipe[description]" id="recipe_description">
Test2</textarea></div>
</li>
<li class="control-group">
<label class="control-label" for="recipe_instruction">Instructions for this recipe</label>
<div class="controls"><textarea rows="10" name="recipe[instruction]" id="recipe_instruction">
Test2</textarea></div>
</li>
</ol>
</fieldset>
<fieldset id="recipe-ingredients">
<ol>
<li class="control-group nested-fields">
<div class="controls">
<label for="recipe_quantities_attributes_0_amount">Amount:</label>
<input type="text" value="111" name="recipe[quantities_attributes][0][amount]" id="recipe_quantities_attributes_0_amount" />
<input type="hidden" name="recipe[quantities_attributes][0][_destroy]" id="recipe_quantities_attributes_0__destroy" value="false" /><a class="remove_fields existing" href="#">remove</a>
</div>
</li>
<input type="hidden" value="38" name="recipe[quantities_attributes][0][id]" id="recipe_quantities_attributes_0_id" />
<li class="control-group nested-fields">
<div class="controls">
<label for="recipe_quantities_attributes_1_amount">Amount:</label>
<input type="text" value="111" name="recipe[quantities_attributes][1][amount]" id="recipe_quantities_attributes_1_amount" />
<input type="hidden" name="recipe[quantities_attributes][1][_destroy]" id="recipe_quantities_attributes_1__destroy" value="false" /><a class="remove_fields existing" href="#">remove</a>
</div>
</li>
<input type="hidden" value="39" name="recipe[quantities_attributes][1][id]" id="recipe_quantities_attributes_1_id" />
<li class="control-group nested-fields">
<div class="controls">
<label for="recipe_quantities_attributes_2_amount">Amount:</label>
<input type="text" value="1111" name="recipe[quantities_attributes][2][amount]" id="recipe_quantities_attributes_2_amount" />
<input type="hidden" name="recipe[quantities_attributes][2][_destroy]" id="recipe_quantities_attributes_2__destroy" value="false" /><a class="remove_fields existing" href="#">remove</a>
</div>
</li>
<input type="hidden" value="40" name="recipe[quantities_attributes][2][id]" id="recipe_quantities_attributes_2_id" />
<li class="control-group nested-fields">
<div class="controls">
<label for="recipe_quantities_attributes_3_amount">Amount:</label>
<input type="text" value="2222" name="recipe[quantities_attributes][3][amount]" id="recipe_quantities_attributes_3_amount" />
<input type="hidden" name="recipe[quantities_attributes][3][_destroy]" id="recipe_quantities_attributes_3__destroy" value="false" /><a class="remove_fields existing" href="#">remove</a>
</div>
</li>
<input type="hidden" value="41" name="recipe[quantities_attributes][3][id]" id="recipe_quantities_attributes_3_id" />
<li class="control-group nested-fields">
<div class="controls">
<label for="recipe_quantities_attributes_4_amount">Amount:</label>
<input type="text" value="33" name="recipe[quantities_attributes][4][amount]" id="recipe_quantities_attributes_4_amount" />
<input type="hidden" name="recipe[quantities_attributes][4][_destroy]" id="recipe_quantities_attributes_4__destroy" value="false" /><a class="remove_fields existing" href="#">remove</a>
</div>
</li>
<input type="hidden" value="42" name="recipe[quantities_attributes][4][id]" id="recipe_quantities_attributes_4_id" />
<li class="control-group nested-fields">
<div class="controls">
<label for="recipe_quantities_attributes_5_amount">Amount:</label>
<input type="text" value="444" name="recipe[quantities_attributes][5][amount]" id="recipe_quantities_attributes_5_amount" />
<input type="hidden" name="recipe[quantities_attributes][5][_destroy]" id="recipe_quantities_attributes_5__destroy" value="false" /><a class="remove_fields existing" href="#">remove</a>
</div>
</li>
<input type="hidden" value="43" name="recipe[quantities_attributes][5][id]" id="recipe_quantities_attributes_5_id" /> </ol>
<a data-association-insertion-node="#recipe-ingredients ol" data-association-insertion-method="append" class="add_fields" data-association="quantity" data-associations="quantities" data-association-insertion-template="<li class="control-group nested-fields">
<div class="controls">
<label for="recipe_quantities_attributes_new_quantities_amount">Amount:</label>
<input type="text" name="recipe[quantities_attributes][new_quantities][amount]" id="recipe_quantities_attributes_new_quantities_amount" />
<input type="text" name="recipe[quantities_attributes][new_quantities][ingredient_attributes][name]" id="recipe_quantities_attributes_new_quantities_ingredient_attributes_name" />
<input type="hidden" name="recipe[quantities_attributes][new_quantities][_destroy]" id="recipe_quantities_attributes_new_quantities__destroy" value="false" /><a class="remove_fields dynamic" href="#">remove</a>
</div>
</li>" href="#">add ingredient</a>
</fieldset>
<input type="submit" name="commit" value="Update Recipe" />
</div>
</form>
<a href="/recipes/2">Show</a> |
<a href="/recipes">Back</a>
</body>
</html>
您的 recipe_params
方法需要更改 - 您的表单中实际上有两层嵌套(配方 -> 数量 -> 成分),因此您的参数许可需要反映这一点。
在您的方法中,删除 ingredient_attributes
和 ingredients_attributes
部分 - 它们与您提交的参数的格式不匹配。相反,您需要如下内容:
:quantities_attributes => [:id, :ingredient, :ingredient_id, :recipe_id, :amount,
:_destroy, :ingredient_attributes => [:id, :_destroy, :ingredient_id, :name]]