Hash with indifferent access

Hash with indifferent access is the actual class of Rails params, so technically speaking it is not just a hash, as I wrote :) The “indifferent access” sounds scary but I am sure you all know what it means. When you want to get a value based on a key, the key can be written as string as well as symbol.

# We will set our new hash with i.a. with one key/value pair dogs = ActiveSupport :: HashWithIndifferentAccess . new dogs [ :husky ] = "Matt" # we can get the value by both, string and symbol dogs [ :husky ] # => "Matt" dogs [ 'husky' ] # => "Matt"

The string and the symbol is treated as a same thing. If you want to explicitely convert all the keys to one or other, you can use stringify_keys or symbolize_keys method. Anyway, if we create a hash with symbol keys, it will be converted to string internally.

symbol_hash = ActiveSupport :: HashWithIndifferentAccess . new symbol_hash [ :foo ] = "bar" symbol_hash # => {"foo" => "bar" }

This is because the []= method is converting keys and values for string every time it is used. Look at the implementation of that method in Rails:

def []= ( key , value ) regular_writer ( convert_key ( key ), convert_value ( value , for :: assignment )) end def convert_key ( key ) key . kind_of? ( Symbol ) ? key . to_s : key end

You should be aware of using regular hashes and hashes with indifferent access as putting these two together may end up unexpectedly. If you merge them together and they contain the same keys, you will end up by having both, not just the later ones.

regular = Hash . new regular [ :one ] = 1 regular [ :two ] = 2 regular # => {:one=>1, :two=>2} indifferent = HashWithIndifferentAccess . new indifferent [ :one ] = "one" regular . merge ( indifferent ) # => {:one=>1, :two=>2, "one"=>"one", "two" => "two" }

Hovewer, if you do it the opposite way (merging regular into indifferent) it will do what is expected and we will have the later values: {"one" => 1, "two" => 2} but it will become also an indifferent hash, so the keys wil be stringified.

P.S. if you want to play with these example in your console, do not forget to include the hash with indifferent acces like this:

require "active_support/hash_with_indifferent_access"

Comments