class ActiveSupport::HashWithIndifferentAccess

which may be handy.
rgb = { black: ‘#000000’, white: ‘#FFFFFF’ }.with_indifferent_access
Note that core extensions define Hash#with_indifferent_access:
example the params hash in Ruby on Rails.
expected keys and it is convenient to understand both as the same. For
but this class is intended for use cases where strings or symbols are the
hash # => {“a”=>1, 0=>0}
= 0
hash = ActiveSupport::HashWithIndifferentAccess.new(a: 1)
Technically other types of keys are accepted:
hash.keys # => [“a”]
You are guaranteed that the key is returned as a string:
hash = ActiveSupport::HashWithIndifferentAccess.new(a: 1)
mapping belongs to the public interface. For example, given:
writing interface (calling []=, merge, etc). This
Internally symbols are mapped to strings when used as keys in the entire<br><br>rgb # => ‘#FFFFFF’<br>rgb # => ‘#FFFFFF’<br>rgb = ‘#FFFFFF’<br><br>rgb # => ‘#000000’<br>rgb # => ‘#000000’<br>rgb = ‘#000000’
rgb = ActiveSupport::HashWithIndifferentAccess.new
to be the same.
Implements a hash where keys :foo and "foo" are considered

def self.[](*args)

def self.[](*args)
  new.merge!(Hash[*args])
end

def self.new_from_hash_copying_default(hash)

def self.new_from_hash_copying_default(hash)
  hash = hash.to_hash
  new(hash).tap do |new_hash|
    new_hash.default = hash.default
  end
end

def []=(key, value)

This value can be later fetched using either +:key+ or +'key'+.

hash[:key] = 'value'
hash = ActiveSupport::HashWithIndifferentAccess.new

Assigns a new value to the hash:
def []=(key, value)
  regular_writer(convert_key(key), convert_value(value, for: :assignment))
end

def convert_key(key)

def convert_key(key)
  key.kind_of?(Symbol) ? key.to_s : key
end

def convert_value(value, options = {})

def convert_value(value, options = {})
  if value.is_a? Hash
    if options[:for] == :to_hash
      value.to_hash
    else
      value.nested_under_indifferent_access
    end
  elsif value.is_a?(Array)
    unless options[:for] == :assignment
      value = value.dup
    end
    value.map! { |e| convert_value(e, options) }
  else
    value
  end
end

def deep_stringify_keys; dup end

def deep_stringify_keys; dup end

def deep_stringify_keys!; self end

def deep_stringify_keys!; self end

def deep_symbolize_keys; to_hash.deep_symbolize_keys end

def deep_symbolize_keys; to_hash.deep_symbolize_keys end

def default(key = nil)

def default(key = nil)
  if key.is_a?(Symbol) && include?(key = key.to_s)
    self[key]
  else
    super
  end
end

def delete(key)

Removes the specified key from the hash.
def delete(key)
  super(convert_key(key))
end

def dup

Returns an exact copy of the hash.
def dup
  self.class.new(self).tap do |new_hash|
    new_hash.default = default
  end
end

def extractable_options?

this class.
Returns +true+ so that Array#extract_options! finds members of
def extractable_options?
  true
end

def fetch(key, *extras)

counters.fetch(:zoo) # => KeyError: key not found: "zoo"
counters.fetch(:bar) {|key| 0} # => 0
counters.fetch(:bar, 0) # => 0
counters.fetch('foo') # => 1

counters[:foo] = 1
counters = ActiveSupport::HashWithIndifferentAccess.new

either a string or a symbol:
Same as Hash#fetch where the key passed as argument can be
def fetch(key, *extras)
  super(convert_key(key), *extras)
end

def initialize(constructor = {})

def initialize(constructor = {})
  if constructor.is_a?(Hash)
    super()
    update(constructor)
  else
    super(constructor)
  end
end

def key?(key)

hash.key?('key') # => true
hash.key?(:key) # => true
hash['key'] = 'value'
hash = ActiveSupport::HashWithIndifferentAccess.new

Checks the hash for a key matching the argument passed in:
def key?(key)
  super(convert_key(key))
end

def merge(hash, &block)

access with the result of the merge.
modify the receiver but rather returns a new hash with indifferent
This method has the same semantics of +update+, except it does not
def merge(hash, &block)
  self.dup.update(hash, &block)
end

def nested_under_indifferent_access

def nested_under_indifferent_access
  self
end

def reject(*args, &block)

def reject(*args, &block)
  dup.tap { |hash| hash.reject!(*args, &block) }
end

def replace(other_hash)

h.replace({ "c" => 300, "d" => 400 }) #=> {"c"=>300, "d"=>400}
h = { "a" => 100, "b" => 200 }

Replaces the contents of this hash with other_hash.
def replace(other_hash)
  super(self.class.new_from_hash_copying_default(other_hash))
end

def reverse_merge(other_hash)

hash.reverse_merge(a: 0, b: 1) # => {"a"=>nil, "b"=>1}
hash['a'] = nil
hash = ActiveSupport::HashWithIndifferentAccess.new

argument and returns a new hash with indifferent access as result:
Like +merge+ but the other way around: Merges the receiver into the
def reverse_merge(other_hash)
  super(self.class.new_from_hash_copying_default(other_hash))
end

def reverse_merge!(other_hash)

Same semantics as +reverse_merge+ but modifies the receiver in-place.
def reverse_merge!(other_hash)
  replace(reverse_merge( other_hash ))
end

def select(*args, &block)

def select(*args, &block)
  dup.tap { |hash| hash.select!(*args, &block) }
end

def stringify_keys; dup end

def stringify_keys; dup end

def stringify_keys!; self end

def stringify_keys!; self end

def symbolize_keys; to_hash.symbolize_keys! end

def symbolize_keys; to_hash.symbolize_keys! end

def to_hash

Convert to a regular hash with string keys.
def to_hash
  _new_hash= {}
  each do |key, value|
    _new_hash[convert_key(key)] = convert_value(value, for: :to_hash)
  end
  Hash.new(default).merge!(_new_hash)
end

def to_options!; self end

def to_options!; self end

def update(other_hash)

hash_1.update(hash_2) { |key, old, new| old + new } # => {"key"=>22}
hash_2['key'] = 12
hash_1[:key] = 10

keys follow the semantics of indifferent access:
in the receiver, and the value in +other_hash+. The rules for duplicated
by the result of invoking the block with the duplicated key, the value
When given a block, the value for duplicated keys will be determined

of the values end up in the receiver, but which one is unspecified.
If the argument is a regular hash with keys +:key+ and +"key"+ only one

In either case the merge respects the semantics of indifferent access.
ActiveSupport::HashWithIndifferentAccess or a regular +Hash+.
The argument can be either an

hash_1.update(hash_2) # => {"key"=>"New Value!"}

hash_2[:key] = 'New Value!'
hash_2 = ActiveSupport::HashWithIndifferentAccess.new

hash_1[:key] = 'value'
hash_1 = ActiveSupport::HashWithIndifferentAccess.new

Updates the receiver in-place, merging in the hash passed as argument:
def update(other_hash)
  if other_hash.is_a? HashWithIndifferentAccess
    super(other_hash)
  else
    other_hash.to_hash.each_pair do |key, value|
      if block_given? && key?(key)
        value = yield(convert_key(key), self[key], value)
      end
      regular_writer(convert_key(key), convert_value(value))
    end
    self
  end
end

def values_at(*indices)

hash.values_at('a', 'b') # => ["x", "y"]
hash[:b] = 'y'
hash[:a] = 'x'
hash = ActiveSupport::HashWithIndifferentAccess.new

Returns an array of the values at the specified indices:
def values_at(*indices)
  indices.collect {|key| self[convert_key(key)]}
end

def with_indifferent_access

def with_indifferent_access
  dup
end