2

This method takes a hash and returns a new hash without sensitive information. It does not modify the hash passed in.

Is there a more Ruby-like, idiomatic way of doing it?

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

Working in Ruby 1.9.3, Sinatra (not Rails) and not using Active Record.

B Seven
  • 44,484
  • 66
  • 240
  • 385

3 Answers3

3

Perhaps something like:

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

You can then call

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

And then sanitize! will modify the Hash in place without duping per Ruby standards.

Eugene
  • 4,829
  • 1
  • 24
  • 49
2
  • It is inefficient to iterate over the protected keys for each key in the hash as in your solution. Rather, just iterate over the protected keys.

  • It is inefficient to generate the array of protected keys each time the method is called. Define that array outside of the method.

The following is better in these respects:

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
sawa
  • 165,429
  • 45
  • 277
  • 381
  • I'd pass in the Protected Keys as an argument to the method. Or you could create a hash subclass with this method and Protected keys as an instance variable. – Fred the Magic Wonder Dog Nov 12 '13 at 19:50
  • That's an improvement in the code. FWIW, the question code does not generate the array of protected keys for each iteration. Perhaps you meant each method invocation? – B Seven Nov 12 '13 at 20:30
  • Right. That was my mistake. – sawa Nov 12 '13 at 20:38
1

And another one:

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)
zwippie
  • 15,050
  • 3
  • 39
  • 54