通过Rails中的关联使用has_many创建新模型时出现不允许的参数错误
Posted
技术标签:
【中文标题】通过Rails中的关联使用has_many创建新模型时出现不允许的参数错误【英文标题】:Unpermitted parameter error in creating new model with has_many through association in Rails 【发布时间】:2015-09-12 17:38:31 【问题描述】:我正在用 Rails 编写一个食谱应用程序。现在我陷入了这个错误。我花了一周的时间来解决这个问题。
更新模型 这是我的模型:
class Recipe < ActiveRecord::Base
has_many :ingredient_recipes
has_many :ingredients, :through => :ingredient_recipes
accepts_nested_attributes_for :ingredient_recipes
end
class Ingredient < ActiveRecord::Base
has_many :ingredient_recipes
has_many :recipes, :through => :ingredient_recipes
end
class IngredientRecipe < ActiveRecord::Base
belongs_to :recipe
belongs_to :ingredient
end
IngredientRecipe 是一个连接模型,用于存储配方和成分的值。
在“新建”操作中,我想创建新配方以及该配方的成分,并指定该成分的数量(数量是连接表成分配方中的附加属性)。
当我点击提交时,它只是创建了一个新配方,并没有在 Join 表中创建记录。
这是我的错误:
Parameters: "utf8"=>"✓",
"authenticity_token"=>"AbnDeDLDWq3lvy4pozvXStVy7NeOIUuv1DU1U2/2EJ6n
/jM6E1669hyB90733XTY9DGAvc2hbbDmbL6NwhqCUg==",
"recipe"=>"rec_name"=>"j", "rec_description"=>"k",
"ingredient_recipe"=>"ingredient"=>"id"=>"1",
"quantity"=>"1", "commit"=>"Create Recipe"
Unpermitted parameter: ingredient_recipe
(0.1ms) BEGIN
SQL (0.2ms) INSERT INTO `recipes` (`rec_name`, `rec_description`,
`created_at`, `updated_at`) VALUES ('j', 'k', '2015-06-25 21:48:09', '2015-06-25 21:48:09')
(1.1ms) COMMIT
Redirected to http://localhost:3000/recipes/50
Completed 302 Found in 6ms (ActiveRecord: 1.4ms)
更新的控制器 我的配方控制器:更新的控制器
def new
@recipe = Recipe.new
3.times @recipe.ingredient_recipes.build.build_ingredient
end
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
我的食谱视图表单:
<%= form_for(@recipe) 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 %>
<div class="field">
<%= f.label :rec_name %><br>
<%= f.text_field :rec_name %>
</div>
<div class="field">
<%= f.label :rec_description %><br>
<%= f.text_area :rec_description %>
</div>
<table>
<thead>
<tr>
<th>Ingredients</th>
<th>Unit</th>
<th>Quantity</th>
<th>New Quantity</th>
</tr>
</thead>
<tbody>
<%= f.fields_for :ingredient_recipes do |fi| %>
<%= fi.fields_for do |i| %>
<tr>
<td> <%=i.collection_select(:ingredient_id, Ingredient.all, :id, :ing_name) %></td>
<% end %>
<td> <%=fi.text_field :quantity %></td>
</tr>
<% end %>
</tbody>
</table>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
更新后没有错误,但这是我提交创建操作时得到的参数:
参数:"utf8"=>"✓", "authenticity_token"=>"NCT4NgS6ZvbqpcS4+CsoYI4pJurYzwsCyj5U6k3MTwSFqDpdLMX+XVFIpAP/pXD3ZDNr6T6mIOf58gUk6SEqOQ==", "recipe"=>"rec_name"=>"s", "rec_description"=>" s", "ingredient_recipes_attributes"=>"0"=>"ingredient_id"=>"2", "quantity"=>"1", "1"=>"ingredient_id"=>"1", "数量"=>"1", "2"=>"ingredient_id"=>"3", "quantity"=>"1", "commit"=>"创建配方"
(0.6ms) 开始
SQL (4.6ms) INSERT INTO recipes
(created_at
, updated_at
) 值 ('2015-07-01 00:37:28', '2015-07-01 00:37:28')
(2.1ms) 提交
重定向到http://localhost:3000/recipes/65
完成 302 Found in 24ms (ActiveRecord: 7.3ms)
于 2015 年 6 月 30 日 17:37:28 -0700 开始为 127.0.0.1 获取“/recipes/65”
由 RecipesController#show 处理为 HTML
参数:"id"=>"65"
配方加载 (4.7ms) SELECT recipes
.* FROM recipes
WHERE recipes
.id
= 65 LIMIT 1
在布局/应用程序中渲染 recipes/show.html.erb (0.7ms)
在 136 毫秒内完成 200 次 OK(查看次数:126.4 毫秒 | ActiveRecord:4.7 毫秒)
似乎一切都在正确的方式上,但我不知道为什么在渲染显示操作之后它没有显示我刚刚添加的配方的属性,它也没有在连接表中创建记录。
请帮帮我!非常感谢
【问题讨论】:
请发布您的strong_params
方法
我的 strong_params: def recipe_params params.require(:recipe).permit(:rec_name, :rec_description, :ingredient_recipes_attributes => [:id, :quantity, :ingredient_attributes => [:id] ])结束
【参考方案1】:
您的模型有错误:
class Ingredient < ActiveRecord::Base
has_many :ingredient_recipes, inverse_of: :ingredient_recipes, autosave: true
has_many :recipes, :through => :ingredient_recipes
以下行不正确。与自身的反比关系无效:
has_many :ingredient_recipes, inverse_of: :ingredient_recipes, autosave: true
这就是您收到错误的原因:
不允许的参数:成分配方
后续步骤(已添加)
从成分模型中删除不正确的 inverse_of 关系 评估您是否需要 inverse_of 关系以及它应该做什么 只有您知道您的应用需要做什么,但如果您需要原始的 inverse_of ingredients_recipes,它应该在这里:class IngredientRecipe < ActiveRecord::Base
belongs_to :recipe, :inverse_of ingredient_recipes
belongs_to :ingredient
accepts_nested_attributes_for :ingredient
end
更多调试建议:删除“自动保存”并显式创建子记录(编辑)
您必须先成功创建父记录,然后才能添加“属于”子项。您的自动保存参数应该执行此操作,但由于某种原因它无法正常工作,您必须对其进行调试。为此,我建议您在创建父配方记录后明确地在子表上创建一个操作。
一旦您通过显式调用正确创建父子记录,然后将自动保存放回模型中,回滚显式创建并查看父保存是否调用子保存。我总是使用显式保存,因为我想控制这个过程。
【讨论】:
那条线我该怎么办?只需删除 inverse_of ? 是的,但还有更多。请查看我添加到答案中的部分。我希望它有所帮助。 我删除了 inverse_of 但它没有用。我仍然得到那个错误。 该错误在 sql 执行之前触发,这就是您看到添加的配方记录的原因。因此,仍然存在模型/控制器错误。我会再深入一点。 我在答案中添加了另一部分。请看一看。以上是关于通过Rails中的关联使用has_many创建新模型时出现不允许的参数错误的主要内容,如果未能解决你的问题,请参考以下文章
如何在has_many中获取模型的属性:通过Rails 5中的关联