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

时间:2013-08-21 06:01:44

标签: ruby-on-rails strong-parameters

我使用以下参数发出http put请求:

  

{ “后”=> { “文件”=> { “file1的”=> “中file_content_1”,   “file2”=>“file_content_2”}},“id”=>“4”}

我需要在我的代码中允许哈希数组。 基于manuals,我尝试过这样的话:

> 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

如何正确使用?

UPD1 :file1,file2 - 是动态键

12 个答案:

答案 0 :(得分:47)

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

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

答案 1 :(得分:29)

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

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

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

答案 2 :(得分:15)

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

这是我发现的另一种解决方案(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"}}

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

[编辑]评论的有用提示

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

答案 3 :(得分:5)

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

这是另一种方式

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

答案 4 :(得分:4)

这是我们在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

答案 5 :(得分:1)

以下是解决此问题的另一种方法:

  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

这适用于post: { something: {...}, something_else: {...} }

答案 6 :(得分:1)

您可以使用临时变量来构建允许列表,如下所示:

permitted = params.require(:post).permit(:id)
permitted[:post][:files] = params[:post][:files].permit!

答案 7 :(得分:1)

这是一种简单的方法(适用于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

答案 8 :(得分:1)

就我而言,只有一个属性具有动态键,

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

答案 9 :(得分:0)

    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

答案 10 :(得分:0)

我没有得到任何许多建议的答案(Rails 5),而没有:

  1. 提前了解所有哈希键,或
  2. 通过允许任意参数来实际上否定强参数的值。
  3. 我正在使用这个解决方案 它使用标准的强参数装置清理大部分参数, 并且显式地添加了Hash属性。

    # Assuming:
    class MyObject < ApplicationRecord
      serialize :hash_attr as: Hash
      #...
    end
    
    # MyObjectsController method to filter params:
    def my_object_params
      # capture the hashed attribute value, as a Hash
      hash_attr = params[:my_object] && params[:my_object][:hash_attr] ?
          params[my_object][:hash_attr].to_unsafe_h : {}
      # clean up the params
      safe_params = params.require(:my_object).permit(:attr1, :attr2) # ... etc
      # and add the hashed value back in
      safe_params.to_unsafe_h.merge hash_attr: hash_attr
    end
    

答案 11 :(得分:0)

让我们使用更复杂的数据子集:

task: {
  code: "Some Task",
  enabled: '1',
  subtask_attributes: { 
    '1' => { field: 'something', rules: {length_10: true, phone: false, presence: false }} ,
    '2' => { field: 'another', rules: {length_10: true, phone: false, presence: false }} 
  }
}

因此,我们将其发送给Strong Parameters进行处理:

params = ActionController::Parameters.new({
  task: {
    code: "Some Task",
    enabled: '1',
    subtask_attributes: { 
     '1' => { field: 'something', rules: {length_10: true, phone: false, presence: false }} ,
     '2' => { field: 'another', rules: {length_10: true, phone: false, presence: false }} 
    }
  }
})

我们将无法在Rails 4的Strong Params中指定:rules,因为它是数据的哈希值:

permitted = params.require(:task).permit(:code, :enabled, subtask_attributes: [:field, :rules])
Unpermitted parameter: rules
Unpermitted parameter: rules

那么如果您想将特定属性和数据哈希集合列入白名单,该怎么办。接受的答案不会将指定的属性列入白名单。您必须这样做:

params.require(:task).permit(
    :code, :enabled,
    subtask_attributes: [:field, :rules],
)

# whitelist the validation rules hash
params.require(:task).tap do |whitelisted|
  params[:task][:subtask_attributes].each do |k,v|
    whitelisted[:subtask_attributes][k] = params[:task][:subtask_attributes][k]
    whitelisted.permit!
  end
end

在这里尝试了几种解决方案后,没有一个起作用。 hasdmany关联中包含任意哈希数据的嵌套属性仅适用于上述情况。