【问题标题】:Rails - Strong Parameters - Nested ObjectsRails - 强参数 - 嵌套对象
【发布时间】:2013-08-28 12:09:47
【问题描述】:

我有一个非常简单的问题。但是目前还没有找到解决办法。

这是我发送到服务器的 JSON 字符串:

{
  "name" : "abc",
  "groundtruth" : {
    "type" : "Point",
    "coordinates" : [ 2.4, 6 ]
  }
}

使用新的许可方法,我得到了:

params.require(:measurement).permit(:name, :groundtruth)

这不会引发错误,但创建的数据库条目包含 null 而不是 groundtruth 值。

如果我只是设置:

params.require(:measurement).permit!

一切都按预期保存,但是当然,这会破坏强参数提供的安全性。

我找到了解决方案,如何允许数组,但没有找到使用嵌套对象的单个示例。这必须以某种方式成为可能,因为它应该是一个非常常见的用例。那么,它是如何工作的呢?

【问题讨论】:

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


【解决方案1】:

当您想要允许嵌套属性时,您确实在数组中指定了嵌套对象的属性,这听起来很奇怪。在你的情况下,它会是

更新 @RafaelOliveira 建议的

params.require(:measurement)
      .permit(:name, :groundtruth => [:type, :coordinates => []])

另一方面,如果你想嵌套多个对象,那么你将它包装在一个哈希中......就像这样

params.require(:foo).permit(:bar, {:baz => [:x, :y]})


Rails 实际上对此有很好的文档:http://api.rubyonrails.org/classes/ActionController/Parameters.html#method-i-permit

为了进一步澄清,您可以查看permitstrong_parameters 本身的实现:https://github.com/rails/rails/blob/master/actionpack/lib/action_controller/metal/strong_parameters.rb#L246-L247

【讨论】:

  • 这两种情况在这个答案中是相同的,实际上,只是花括号在 { :groundtruth => [...]}; 周围是可选的;它是一个散列,但解释器能够确定散列的开始和结束位置,而无需显式大括号。
  • 属性的嵌套数组不允许嵌套属性。嵌套属性和 attr_accessor 在我的应用程序中列为“不允许的参数”。仍在寻找安全的解决方案。
  • 在多个嵌套对象的情况下,您还应该允许 id 使其工作。更多信息在这里:stackoverflow.com/questions/18308714/…
  • 这只允许一组嵌套属性。这在一对多的情况下不起作用。
  • @speakingcode 如果是这种情况,我怀疑最好保留大括号,这样代码的读者可以更清楚地了解发生了什么
【解决方案2】:

我发现这个建议对我来说很有用:

  def product_params
    params.require(:product).permit(:name).tap do |whitelisted|
      whitelisted[:data] = params[:product][:data]
    end
  end

查看link Xavier 在 github 上的评论。

这种方法将整个 params[:measurement][:groundtruth] 对象列入白名单。

使用原始问题属性:

  def product_params
    params.require(:measurement).permit(:name, :groundtruth).tap do |whitelisted|
      whitelisted[:groundtruth] = params[:measurement][:groundtruth]
    end
  end

【讨论】:

  • 只是一个旁注,这仍然会在日志中显示为未经允许的参数,但模型无论如何都会接受它们。
  • 不确定 Rails 4 但在我的 Rails 5 项目中,我必须调用 permit! 才能将其列入白名单,否则在点击它后仍然不允许。在这种情况下,它将是 params[:measurement][:groundtruth].permit!
  • @nayiaw 我也收到了未经许可的消息,但添加 permit! 会引发此错误 NoMethodError (undefined method permit!'对于#<0x007f80cb71ea00>
  • <a href="/default/index/tourl?u=aHR0cDovL2FwaS5ydWJ5b25yYWlscy5vcmcvY2xhc3Nlcy9BY3Rpb25Db250cm9sbGVyL1BhcmFtZXRlcnMuaHRtbCNtZXRob2QtaS1wZXJtaXQ%3D" rel="nofollow" target="_blank"></a>
【解决方案3】:

允许嵌套对象:

params.permit( {:school => [:id , :name]}, 
               {:student => [:id, 
                            :name, 
                            :address, 
                            :city]},
                {:records => [:marks, :subject]})

【讨论】:

    【解决方案4】:

    如果是 Rails 5,由于新的哈希表示法: params.permit(:name, groundtruth: [:type, coordinates:[]]) 可以正常工作。

    【讨论】:

      猜你喜欢
      • 2014-06-12
      • 1970-01-01
      • 2015-09-20
      • 1970-01-01
      • 1970-01-01
      • 2014-10-20
      • 2013-10-14
      • 2014-08-14
      相关资源
      最近更新 更多