我有一个带有子类QueryGroup的模型QueryElement。 QueryGroup可以包含嵌套的QueryElements。
Say QueryGroup有一个属性名,而QueryElement有一个属性过滤器(仅作为例)
因此,对于强参数,我有类似的东西:
params.fetch(:query).permit(:name, :filter, :query_elements => [:name, :filter, :query_elements => [...]
等等。
我可以允许所有(破坏强参数的安全性,我宁愿避免),或者手动遍历树,这要慢得多。这是我目前的做法。
有更好的方法吗?
答案 0 :(得分:0)
这样的事情:
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
可能会有一些改进,比如将密钥转换为符号,有更好的错误消息告诉你哪个嵌套级别有丢失的密钥等等。