How to Access a Hash with both String and Symbol Keys in Rails

Hash with Indifferent Access
Hash with Indifferent Access

Sometimes, you receive a hash key as a method parameter or via user input, and you want to make your hash understand that key as-is, without worrying if it's a string or a symbol. A good example is the params hash in Rails. You can access it using either a string or a symbol.

If you try to access a regular Ruby hash with a non-existent key, it returns nil value.

ak = {
  name: 'Akshay',
  age: 30
}

ak[:name]   # "Akshay"
ak['name']  # nil

Rails provides the ActiveSupport::HashWithIndifferentAccess class which implements a hash where keys :foo and "foo" are considered to be the same.

h = ActiveSupport::HashWithIndifferentAccess.new

h[:name] = 'akshay'

h[:name]   # "akshay"
h['name']  # "akshay"

If that long class name looks intimidating, don't worry, you don't have to initialize this class yourself. Instead, use the with_indifferent_access extension method.

ak = {
  name: 'Akshay',
  age: 30
}

h = ak.with_indifferent_access

h[:name]    # "Akshay"
h['name']   # "Akshay"

The with_indifferent_access method is added by Active Support by monkey-patching the Hash class.

# lib/active_support/core_ext/hash/indifferent_access.rb

class Hash
  def with_indifferent_access
    ActiveSupport::HashWithIndifferentAccess.new(self)
  end
end

As seen above, this method returns a new instance of the ActiveSupport::HashWithIndifferentAccess class, initializing it with the current hash. This class supports all the existing hash API, so you can call any method you'd call on a regular Ruby hash.

Subscribe to Akshay's Blog

Sign up now to get access to the library of members-only issues.
Jamie Larson
Subscribe