Ruby-on-rails Rails4:如何在参数中允许带有动态键的哈希?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18349887/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Rails4: How to permit a hash with dynamic keys in params?
提问by rdo
I make a http put request with following parameters:
我使用以下参数发出 http put 请求:
{"post"=>{"files"=>{"file1"=>"file_content_1", "file2"=>"file_content_2"}}, "id"=>"4"}
{"post"=>{"files"=>{"file1"=>"file_content_1", "file2"=>"file_content_2"}}, "id"=>"4"}
and i need to permit hash array in my code. based on manualsI've tried like these:
我需要在我的代码中允许哈希数组。基于我尝试过的手册:
> 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
How to make it correctly?
如何正确制作?
UPD1: file1, file2 - are dynamic keys
UPD1: file1, file2 - 是动态键
回答by Orlando
By design strong params doesn't allow hashes with dynamic keys as values, in this case you need to whitelist filesby calling permit!
通过设计强参数不允许使用动态键作为值的散列,在这种情况下,您需要files通过调用白名单permit!
params.require(:post).tap do |whitelisted|
whitelisted[:files] = params[:post][:files].permit!
end
For Rails 4 and below you do it without calling permit!
对于 Rails 4 及以下版本,您无需调用即可 permit!
params.require(:post).tap do |whitelisted|
whitelisted[:files] = params[:post][:files]
end
回答by Derek
In rails 5.1.2, this works now:
在 rails 5.1.2 中,这现在有效:
params.require(:post).permit(:files => {})
See https://github.com/rails/rails/commit/e86524c0c5a26ceec92895c830d1355ae47a7034
见https://github.com/rails/rails/commit/e86524c0c5a26ceec92895c830d1355ae47a7034
回答by wes.hysell
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):
这是我发现有效的替代解决方案(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.
此答案与已接受的答案之间的区别在于,此解决方案将参数限制为仅 1 级动态键。接受的答案允许多个深度。
[Edit] Useful tip from comment
[编辑] 来自评论的有用提示
"Oh, and you need to verify that params[:post][.files] exists otherwise keys will fail"
“哦,您需要验证 params[:post][.files] 是否存在,否则密钥将失败”
回答by Toby 1 Kenobi
Orlando's answer works, but the resulting parameter set returns falsefrom the permitted?method. Also it's not clear how you would proceed if you were to later have other parameters in the posthash that you want included in the result.
奥兰多的答案有效,但结果参数集false从该permitted?方法返回。此外,如果您以后要在post散列中包含其他想要包含在结果中的参数,那么您将如何进行也不清楚。
Here's another way
这是另一种方式
permitted_params = params.require(:post).permit(:other, :parameters)
permitted_params.merge(params[:post][:files])
回答by Garry Gomez
Here's what we had to do in Rails 5.0.0, hope this helps someone.
这是我们在 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
回答by Mukarram Ali
In my case, there was just one attribute which had dynamic keys,
就我而言,只有一个属性具有动态键,
def post_params
marking_keys = Set.new
params[:post][:marking].keys.collect {|ii| marking_keys.add(ii)}
params.require(:post).permit(:name, marking: marking_keys.to_a)
end
回答by Krzysztof Karski
Here's a simple way to do it (works for rails 5):
这是一个简单的方法(适用于 rails 5):
def my_params
data_params = preset_data_params
params.require(:my_stuff).permit(
:some,
:stuff,
data: data_params
)
end
def preset_data_params
return {} unless params[:my_stuff]
return {} unless params[:my_stuff][:data]
params[:my_stuff][:data].keys
end
回答by Sash
Here is another way to get around this:
这是解决此问题的另一种方法:
def post_params
permit_key_params(params[:post]) do
params.require(:post)
end
end
def permit_key_params(hash)
permitted_params = yield
dynamic_keys = hash.keys
dynamic_keys.each do |key|
values = hash.delete(key)
permitted_params[key] = values if values
end
permitted_params
end
This should work for post: { something: {...}, something_else: {...} }
这应该适用于 post: { something: {...}, something_else: {...} }
回答by Cam
You can use a temporary variable to build your permitted list like so:
您可以使用临时变量来构建允许的列表,如下所示:
permitted = params.require(:post).permit(:id)
permitted[:post][:files] = params[:post][:files].permit!
回答by vikas pal
Send params as array type like name=date[]**strong text**
def user_post
dates = params[:date]
#render json: { 'response' => params }
i = 0
dates.each do |date|
locations = params['location_'+"#{i}"]
user_names = params['user_'+"#{i}"]
currency_rates = params['currency_'+"#{i}"]
flags = params['flag_'+"#{i}"]
j = 0
locations.each do |location|
User.new(user_name: user_names[j], currency_name: flags[j],
currency_rate: currency_rates[j], currency_flag: flags[j], location: location).save
j =+ 1
end
i =+ 1
end
def

