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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 22:34:03  来源:igfitidea点击:

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

ruby-on-railsstrong-parameters

提问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