【问题标题】:Rails 4 nested attribute hash keys showing as unpermittedRails 4嵌套属性哈希键显示为未经许可
【发布时间】:2015-02-25 22:15:16
【问题描述】:

我有一个Category 模型和一个Standard 模型。一个类别通过“连接表”模型CategoryStandard 有许多标准。在我看来,我有一个表单,我可以在其中编辑类别描述,然后在该类别中添加或删除标准。所以,我的嵌套属性是针对:category_standards,因为我不是在编辑标准本身,只是添加或删除关系,如果这有意义的话。

这是视图的重要部分:

<%= form_for(@category) do |f| %>
...
  <div class="field">
    <%= f.label :description %>
    <%= f.text_field :description %>
  </div>

  <%= label_tag nil, "Standards in this Category" %>
  <div id="standard-list">
    <%= f.fields_for :category_standards do |ff| %>
      <div class="field">
        <%= ff.object.standard.number_with_exceptions %>
        <%= ff.hidden_field :standard_id %>
        <%= ff.hidden_field :_destroy %>
        <%= link_to "<span class='glyphicon glyphicon-remove'></span>".html_safe, "", class: "del-std-btn", title: "Remove standard from category" %>
      </div>
    <% end %>

    <div class="hidden" id="std-add-new-template">
      <div class="field">
        <%= f.fields_for :category_standards, CategoryStandard.new, child_index: "new_id" do |ff| %>
          <%= ff.collection_select :standard_id, @standards - @category.standards, :id, :number_with_exceptions, prompt: "Select a standard to add" %>
        <% end %>
      </div>
    </div>
  </div>
...
<% end %>

引擎盖下有一些 jQuery 来操纵“行”,但效果很好,我不认为这是我的问题的一部分,所以我会省略它。

在我的类别模型中,我有:

class Category < ActiveRecord::Base
  has_many :category_standards, dependent: :destroy
  has_many :standards, through: :category_standards
  validates :description, presence: true,
                          uniqueness: true
  accepts_nested_attributes_for :category_standards, allow_destroy: true, reject_if: proc { |attributes| attributes['standard_id'].blank?}
end

在我的类别控制器中,我有:

def category_params
  params.require(:category).permit(:description, category_standards_attributes: [:id, :standard_id, :_destroy])
end

但是当我尝试将标准添加到类别时,我会在服务器日志中看到这些行(重新格式化以使其更具可读性):

Parameters: {"utf8"=>"✓",
              "authenticity_token"=>"***********",
              "category"=>{
                "description"=>"Drinking Water System Components", 
                "category_standards_attributes"=>{
                  "0"=>{
                    "standard_id"=>"2",
                    "_destroy"=>"false",
                    "id"=>"1"
                  }, 
                  "new_id"=>{
                    "standard_id"=>""
                  },
                  "1424899001814"=>{
                    "standard_id"=>"1"
                  }
                }
              },
              "commit"=>"Save Changes",
              "id"=>"2"
            }

User Load (5.0ms)  SELECT "users".* FROM "users" WHERE "users"."id" = 1 ORDER BY "users"."id" ASC LIMIT 1

Category Load (4.0ms)  SELECT "categories".* FROM "categories" WHERE "categories"."id" = $1 LIMIT 1  [["id", "2"]]

Unpermitted parameters: 0, new_id, 1424899001814

(4.0ms)  BEGIN
Category Exists (6.0ms)  SELECT 1 AS one FROM "categories" WHERE ("categories"."description" = 'Drinking Water System Components' AND "categories"."id" != 2) LIMIT 1

SQL (6.0ms)  UPDATE "categories" SET "description" = $1, "updated_at" = $2 WHERE "categories"."id" = 2  [["description", "Drinking Water System Components"], ["updated_at", Wed, 25 Feb 2015 21:16:44 UTC +00:00]]

它可以很好地更新描述字段,但是 Unpermitted 参数是怎么回事?我的属性散列就像 Rails 指南中nested forms 中的示例一样,它甚至说“:addresses_attributes 散列的键并不重要,它们只需要每个地址不同。”然而,对我来说却是钥匙被拒绝了。

我哪里做错了?谢谢!

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-4 nested-attributes


    【解决方案1】:

    经过大量阅读后想通了。缺少的部分是here

    具有整数键的散列被不同地处理,您可以将属性声明为就好像它们是直接子级一样。当您将accepts_nested_attributes_for 与has_many 关联结合使用时,您会得到这些类型的参数:

    # To whitelist the following data:
    # {"book" => {"title" => "Some Book",
    #             "chapters_attributes" => { "1" => {"title" => "First Chapter"},
    #                                        "2" => {"title" => "Second Chapter"}}}}
    
    params.require(:book).permit(:title, chapters_attributes: [:title])
    

    其中重要的部分是“带有 integer 键的散列”。我的哈希键以“0”、“new_id”、“1240934304343”的形式传递。我使用“new_id”并不重要,因为这只是一个占位符值,当添加新行时会在我的 jQuery 中更改。只有模板行保留了该值,这很好,因为它被我的reject_if 子句过滤掉了。

    但“new_id”不是一个整数这一事实显然是把事情搞砸了。所以我把它改成了“-1”,Rails 接受它(即使它仍然被reject_if 过滤掉,应该是这样)。

    <div class="hidden" id="std-add-new-template">
      <div class="field">
        <%= f.fields_for :category_standards, CategoryStandard.new, child_index: "-1" do |ff| %>
          <%= ff.collection_select :standard_id, @standards - @category.standards, :id, :number_with_exceptions, prompt: "Select a standard to add" %>
        <% end %>
      </div>
    </div>
    

    【讨论】:

      【解决方案2】:

      您的属性键似乎与您在强参数中所期望的不匹配,“new_id”和“1424899001814”当然不会被允许。

      "new_id"=>{
          "standard_id"=>""
      },
      "1424899001814"=>{
          "standard_id"=>"1"
      }
      

      我怀疑您构建表单的方式无效。尝试将其分解为最简单的工作形式。例如:

          <div id="standard-list">
              <%= link_to "<span class='glyphicon glyphicon-remove'></span>".html_safe, "", class: "del-std-btn", title: "Remove standard from category" %>
      
              <div class="hidden" id="std-add-new-template">
                <div class="field">
                  <%= f.fields_for :category_standards do |ff| %>
                      <%= ff.object.standard.number_with_exceptions %>
                      <%= ff.hidden_field :standard_id %>
                      <%= ff.hidden_field :_destroy %>
                      <%= ff.collection_select :standard_id, @standards - @category.standards, :id, :number_with_exceptions, prompt: "Select a standard to add" %>
                  <% end %>
                </div>
              </div>
          </div>
      

      目的是只有一个嵌套形式,通过剥离它只创建一个嵌套哈希。

      "category_standards_attributes"=>{
          "0"=>{
              "standard_id"=>"2",
              "_destroy"=>"false",
              "id"=>"1"
          }
      }
      

      这会发生什么?

      【讨论】:

      • 谢谢,但这似乎不起作用。我仍然收到相同类型的错误:Unpermitted parameters: 0, new_id, 1424906638629
      • 谢谢!我认为你在正确的轨道上,但我终于读到了一些让我“啊哈”时刻的东西。请参阅下面的答案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多