通过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中的关联

如何通过rails中的关联定义has_many

如何区分相似的has_many:通过Rails中的关联?

带有has_many的模型中的属性总和:通过关联在Rails 5中不起作用

如何将记录添加到has_many:通过rails中的关联

Rails:has_many 通过关联 - 我做对了吗?