【问题标题】:Strong parameters with nested hash具有嵌套哈希的强参数
【发布时间】:2015-09-24 16:25:23
【问题描述】:

我有以下参数,无法让强参数工作。

这是我的基本代码,为简单起见,可在 Rails 控制台中运行:

json = {
  id: 1,
  answers_attributes: {
    c1: { id: "", content: "Hi" },
    c2: { id: "", content: "Ho" }
  }
}

params = ActionController::Parameters.new(json)

我读过的所有内容都说以下内容应该可以工作,但它只给了我idanswers_attributes 的空哈希:

params.permit(:id, answers_attributes: [:id, :content])
=> { "id"=>1, "answers_attributes"=>{} }

如果我改为手动列出c1c2(如下所示),它可以工作,但这真的很愚蠢,因为我不知道用户会提供多少答案,这是很多重复:

params.permit(:id, answers_attributes: { c1: [:id, :content], c2: [:id, :content] })
=> {"id"=>1, "answers_attributes"=>{"c1"=>{"id"=>"", "content"=>"Hi"}, "c2"=>{"id"=>"", "content"=>"Ho"}}}

我尝试将c1c2 替换为01,但我仍然需要在我的许可声明中手动提供01

如何允许未知长度的嵌套属性数组?

【问题讨论】:

    标签: ruby-on-rails ruby strong-parameters


    【解决方案1】:

    使用如下语法完成:

    answers_attributes: [:id, :content]
    

    问题在于您在answers_attributes 中使用的密钥。它们应该是answers_attributes 的ID,或者在新记录的情况下是0

    改变这些会得到你预期的结果:

    json = {
      id: 1,
      answers_attributes: {
        "1": { id: "", content: "Hi" },
        "2": { id: "", content: "Ho" }
      }
    }
    
    params = ActionController::Parameters.new(json)
    
    params.permit(:id, answers_attributes:[:id, :content])
    =>  {"id"=>1, "answers_attributes"=>{"1"=>{"id"=>"", "content"=>"Hi"}, "2"=>{"id"=>"", "content"=>"Ho"}}}
    

    编辑:看来 0 不是唯一的键,我的意思是如果你有两个 new 记录怎么办。我使用nested_form,它似乎使用了一个很长的随机数。

    【讨论】:

    • 你特意说"in the case of new records"。这是否也适用于已编辑的记录?
    • 已编辑的记录不是新记录,因此您可以将 id 作为键。
    • 谢谢,这似乎确实可以解决问题。奇怪的是它必须是数字的字符串表示,而不是实际数字,但我可以让它工作。感谢您的帮助!
    • @TopherFangio 我不认为它们必须是字符串。我会编辑答案。
    【解决方案2】:

    您的answers_attributes 包含不允许的 c1 和 c2。 http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html

    方式 1:您可以将嵌套属性作为哈希数组传递。

    json = {
      id: 1,
      answers_attributes: [ { id: "", content: "Hi" }, { id: "", content: "Ho" } ]
    }
    

    现在params.permit(:id, answers_attributes: [:id, :content]) 给了

    {"id"=>1, "answers_attributes"=>[{"id"=>"", "content"=>"Hi"}, {"id"=>"", "content"=>"Ho"}]}
    

    方式2:你可以像散列一样传递散列

    json = {
      id: 1,
      answers_attributes: {
        c1: { id: "", content: "Hi" },
        c2: { id: "", content: "Ho" }
      }
    }
    

    WAY 1WAY 2在模型层级的效果是一样的。但是permit 不允许值传递,除非明确指定键。所以 c1c2 除非明确指定,否则将不允许使用

    params.permit(:id, answers_attributes: [c1: [:id, :content], c2: [:id, :content]])
    

    这真是让人头疼。

    【讨论】:

    • c1c2 确实对accepts_nested_attributes_for 有效,因为这一直有效,并且在我开始使用permit 之前已经保存了数据。问题是permit 调用不理解此语法,并且没有将其传递给要保存的模型。 编辑:值得注意的是,如果您使用该 JSON,上述方式 2 也不适用于许可。
    • 感谢您的通知。正如@TopherFangio 提到的,除非我们明确指定密钥,否则 permit 不允许值通过。我将编辑我的答案。
    猜你喜欢
    • 2018-07-12
    • 1970-01-01
    • 2013-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-10
    • 2011-03-31
    相关资源
    最近更新 更多