【问题标题】:How to refactor this Ruby sanitize hash method to make it more idiomatic?如何重构这个 Ruby 清理散列方法以使其更惯用?
【发布时间】:2013-11-25 02:49:04
【问题描述】:

此方法采用哈希并返回不包含敏感信息的新哈希。它不会修改传入的哈希。

有没有更类似于 Ruby 的惯用方式?

def sanitize hash
  new_hash = hash.dup
  protected_keys = [ :password, 'password', :confirmation, 'confirmation' ]

  new_hash.each do |k,v|
    if protected_keys.include?( k ) && ! v.blank?
      new_hash[ k ] = 'xxxxxxxxx'
    end
  end

  new_hash
end

在 Ruby 1.9.3、Sinatra(不是 Rails)和中使用 Active Record。

【问题讨论】:

  • 我认为您不恰当地使用了“消毒”一词。在编程上下文中,sanitize 意味着转义特殊字符。
  • 好的,有什么更好的名字?保护?
  • 也许“隐藏”或“掩码”更好。
  • 如果你没有使用 Rails 或 Active Record,blank? 来自哪里?

标签: ruby sinatra hashtable ruby-1.9.3


【解决方案1】:
  • 在您的解决方案中,为散列中的每个键迭代受保护的键是低效的。相反,只需遍历受保护的密钥。

  • 每次调用该方法时生成受保护密钥数组的效率很低。在方法之外定义该数组。

以下方面在这些方面更好:

ProtectedKeys = %w[password confirmation]
def sanitize hash
  new_hash = hash.dup
  ProtectedKeys.each do |k| [k, k.to_sym].each do |k|
    new_hash[k] = "xxxxxxxxx" if new_hash.key?(k) and new_hash[k].present?
  end end
  new_hash
end

【讨论】:

  • 我会将受保护的密钥作为参数传递给该方法。或者您可以使用此方法创建一个哈希子类,并将受保护的键作为实例变量。
  • 这是对代码的改进。 FWIW,问题代码不会为每次迭代生成受保护的密钥数组。也许您的意思是每个方法调用?
  • 对。那是我的错误。
【解决方案2】:

还有一个:

def sanitize(params)
  protected_keys = %(password confirmation)
  replacement = 'xxxxxx'
  new_params = params.dup
  new_params.each_key {|key| new_params[key] = replacement if protected_keys.include?(key.to_s)}
end

test_hash = {
  name: 'Me',
  password: 'secret',
  address: 'Here',
  confirmation: 'secret'
}
puts sanitize(test_hash)

【讨论】:

    【解决方案3】:

    可能是这样的:

    class Hash
      def sanitize(*keys)
        new_hash = self.dup
        new_hash.each do |k,v| 
          if keys.include?(k) && ! v.empty?
            new_hash[k] = 'xxxxxxxxxx'
          end
        end
      end
    
      def sanitize!(*keys)
        self.each do |k,v|
          if keys.include?(k) && ! v.empty?
            self[k] = 'xxxxxxxxxx'
          end
        end
      end
    end
    

    然后你可以调用

    hash = {password: "test", name: "something"}
    sanitized_hash = hash.sanitize(:password, 'password', :confirmation, 'confirmation')
    

    然后sanitize! 将根据 Ruby 标准修改 Hash 而不重复。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-13
      相关资源
      最近更新 更多