Rails4: How to permit a hash with dynamic keys in params?

I understand that this is an old post. However, a Google search brought me to this result, and I wanted to share my findings:

Here is an alternative solution that I have found that works (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"}}

The difference between this answer and the accepted answer, is that this solution restricts the parameter to only 1 level of dynamic keys. The accepted answer permits multiple depths.

[Edit] Useful tip from comment

"Oh, and you need to verify that params[:post][.files] exists otherwise keys will fail"


In rails 5.1.2, this works now:

params.require(:post).permit(:files => {})

See https://github.com/rails/rails/commit/e86524c0c5a26ceec92895c830d1355ae47a7034


Orlando's answer works, but the resulting parameter set returns false from the permitted? method. Also it's not clear how you would proceed if you were to later have other parameters in the post hash that you want included in the result.

Here's another way

permitted_params = params.require(:post).permit(:other, :parameters)
permitted_params.merge(params[:post][:files])

Rails 5.1+

params.require(:post).permit(:files => {})

Rails 5

params.require(:post).tap do |whitelisted|
  whitelisted[:files] = params[:post][:files].permit!
end

Rails 4 and below

params.require(:post).tap do |whitelisted|
  whitelisted[:files] = params[:post][:files]
end