Rails4:如何在params中允许使用动态键的哈希?

rdo*_*rdo 42 ruby-on-rails strong-parameters

我使用以下参数创建一个http put请求:

{"post"=> {"files"=> {"file1"=>"file_content_1","file2"=>"file_content_2"}},"id"=>"4"}

我需要在我的代码中允许哈希数组.基于手册,我尝试过这样:

> params.require(:post).permit(:files) # does not work
> params.require(:post).permit(:files => {}) # does not work, empty hash as result
> params.require(:post).permit! # works, but all params are enabled
Run Code Online (Sandbox Code Playgroud)

如何正确使用?

UPD1:file1,file2 - 是动态密钥

Orl*_*ndo 53

通过设计强params不允许使用动态键作为值的哈希,因此..在这种情况下,您需要files手动将白名单.

params.require(:post).tap do |whitelisted|
  whitelisted[:files] = params[:post][:files].permit!
end
Run Code Online (Sandbox Code Playgroud)

  • 以下是"tap"的工作原理:http://ruby-doc.org/core-2.1.1/Object.html#method-i-tap (5认同)
  • 仅供参考,在Rails 5.0中,您需要在params [:post] [:files]上调用`permit!`才能正常工作 (2认同)

Der*_*rek 38

在rails 5.1.2中,现在可以使用:

params.require(:post).permit(:files => {})
Run Code Online (Sandbox Code Playgroud)

请参阅https://github.com/rails/rails/commit/e86524c0c5a26ceec92895c830d1355ae47a7034

  • 请注意,如果“post”中有多个允许的参数,则散列参数(在本例中为“files”)必须是“permit()”列表中的最后一个,否则您将收到语法错误。 (3认同)
  • 但是如果“files”嵌套了多层怎么办?例如 `params['post']['mymodel_attributes']['things']['files']` 和 `files` 可以是带有任何键的哈希? (2认同)
  • 不幸的是这对我不起作用。它导致过滤后的参数中出现文字“{}”。不过,我解决了这个问题:P StrongParams 的深度嵌套输入数据处理起来并不有趣。StrongParameter 语法的改进会很好。 (2认同)

wes*_*ell 16

我知道这是一篇旧帖子.但是,谷歌搜索带我到这个结果,我想分享我的发现:

这是我发现的另一种解决方案(Rails 4):

params = ActionController::Parameters.new({"post"=>{"files"=>{"file1"=>"file_content_1", "file2"=>"file_content_2"}}, "id"=>"4"})
params.require(:post).permit(files: params[:post][:files].keys)
# Returns: {"files"=>{"file1"=>"file_content_1", "file2"=>"file_content_2"}}
Run Code Online (Sandbox Code Playgroud)

此答案与已接受答案之间的区别在于此解决方案将参数限制为仅1级动态键.接受的答案允许多个深度.

[编辑]评论的有用提示

"哦,你需要验证params [:post] [.files]是否存在,否则键将失败"

  • 哦,你需要验证params [:post] [.files]是否存在,否则键将失败 (4认同)

Tob*_*obi 5

奥兰多的答案有效,但结果参数集false从permitted?方法返回.如果您稍后在post哈希中包含您希望包含在结果中的其他参数,那么您还不清楚如何继续.

这是另一种方式

permitted_params = params.require(:post).permit(:other, :parameters)
permitted_params.merge(params[:post][:files])
Run Code Online (Sandbox Code Playgroud)


Gar*_*mez 5

这是我们在 Rails 5.0.0 中必须做的事情,希望这对某人有所帮助。

files = params[:post].delete(:files) if params[:post][:files]
params.require(:post).permit(:id).tap do |whitelisted|
  whitelisted[:files] = files.permit!
end
Run Code Online (Sandbox Code Playgroud)