【问题标题】:Rails strong parameters for infinitely nestable model无限可嵌套模型的Rails强参数
【发布时间】:2017-11-15 14:36:45
【问题描述】:

我有一个模型 QueryElement,它有一个子类 QueryGroup。 QueryGroup 可以包含嵌套的 QueryElements。

假设 QueryGroup 有一个属性名,而 QueryElement 有一个属性过滤器(仅作为示例)

所以对于强参数,我有类似的东西:

params.fetch(:query).permit(:name, :filter, :query_elements => [:name, :filter, :query_elements => [...]

等等。

我可以允许所有(破坏强参数的安全性,我宁愿避免),或者手动逐步遍历树,这要慢得多。这是我目前的做法。

有没有更好的办法?

【问题讨论】:

  • “慢得多”是什么意思?
  • 这些对象往往嵌套得很深,因此对每个请求逐个遍历这些大树并不理想
  • 我想递归过滤函数可以正常工作。自定义,使用Hash#slice(或其他),不是强参数
  • 实际上它被称为复合模式,它是文件系统工作方式的基础
  • 您可能希望在嵌套中允许最大深度,正如@SergioTulentsev 所说,递归函数可能使用强参数或Hash#slice(=allow)/Hash#fetch_values 的组合(=required) 这应该更有效

标签: ruby-on-rails strong-parameters


【解决方案1】:

类似这样的:

REQUIRED = %i( name ).freeze
ALLOWED = (%i( filter query_elements ) + REQUIRED).freeze
MAX_DEPTH = 5

def ensure_params(hash, nest_level = 0) # ah I never come up with good names...
  raise 'you went too deep man' if nest_level > MAX_DEPTH
  hash.fetch_values(*REQUIRED)
  hash[:query_elements] = ensure_params(hash[:query_elements], nest_level + 1) if hash[:query_elements]
  hash.slice(*ALLOWED)
end

在 IRB 中:

> ensure_params({ :filter => 2, :name => 'test', unpermitted_param: :something, :query_elements => { filter: 3, name: 'test', nested_unpermitted: 13 } })
# => {:filter=>2, :query_elements=>{:filter=>3, :name=>"test"}, :name=>"test"} 
> ensure_params({ name: 1, query_elements: { notname: 1 } })
KeyError: key not found: :name
> MAX_DEPTH = 3
# => 3 
> ensure_params({ name: 1, query_elements: { name: 1, query_elements: { name: 1, query_elements: { name: 1, query_elements: { name: 1, query_elements: { name: 1 } } } } }})
RuntimeError: you went too deep man

可能可以进行一些改进,例如将键转换为符号,有更好的错误消息告诉您在哪个嵌套级别缺少键等。

【讨论】:

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