class ActiveSupport::HashWithIndifferentAccess

which will, in turn, require this file.
require “active_support/core_ext/hash/indifferent_access”
To access this class outside of Rails, require the core extension with:
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 [](key)

counters[:zoo] # => nil
counters[:foo] # => 1
counters['foo'] # => 1

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

either a string or a symbol:
Same as Hash#[] where the key passed as argument can be
def [](key)
  super(convert_key(key))
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, conversion: :assignment))
end

def assoc(key)

counters.assoc(:zoo) # => nil
counters.assoc(:foo) # => ["foo", 1]
counters.assoc('foo') # => ["foo", 1]

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

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

def compact

def compact
  dup.tap(&:compact!)
end

def convert_key(key)

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

def convert_key(key)

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

def convert_value(value, conversion: nil)

def convert_value(value, conversion: nil)
  if value.is_a? Hash
    if conversion == :to_hash
      value.to_hash
    else
      value.nested_under_indifferent_access
    end
  elsif value.is_a?(Array)
    if conversion != :assignment || value.frozen?
      value = value.dup
    end
    value.map! { |e| convert_value(e, conversion: conversion) }
  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(*args)

hash.default(:foo) # => 'foo'
hash.default('foo') # => 'foo'
hash.default # => nil
hash = ActiveSupport::HashWithIndifferentAccess.new { |hash, key| key }

hash.default # => 1
hash = ActiveSupport::HashWithIndifferentAccess.new(1)

either a string or a symbol:
Same as Hash#default where the key passed as argument can be
def default(*args)
  super(*args.map { |arg| convert_key(arg) })
end

def delete(key)

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

def dig(*args)

counters.dig(:zoo) # => nil
counters.dig(:foo, :bar) # => 1
counters.dig('foo', 'bar') # => 1

counters[:foo] = { bar: 1 }
counters = ActiveSupport::HashWithIndifferentAccess.new

either a string or a symbol:
Same as Hash#dig where the key passed as argument can be
def dig(*args)
  args[0] = convert_key(args[0]) if args.size > 0
  super(*args)
end

def dup

dup[:a][:c] # => "c"
hash[:a][:c] # => "c"

dup[:a][:c] = 'c'
dup = hash.dup
hash = ActiveSupport::HashWithIndifferentAccess.new({ a: { b: 'b' } })

Returns a shallow copy of the hash.
def dup
  self.class.new(self).tap do |new_hash|
    set_defaults(new_hash)
  end
end

def except(*keys)

hash # => { a: "x", b: "y", c: 10 }.with_indifferent_access
hash.except(:a, "b") # => {c: 10}.with_indifferent_access
hash = { a: "x", b: "y", c: 10 }.with_indifferent_access
Returns a hash with indifferent access that includes everything except given keys.
def except(*keys)
  slice(*self.keys - keys.map { |key| convert_key(key) })
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 fetch_values(*indices, &block)

hash.fetch_values('a', 'c') # => KeyError: key not found: "c"
hash.fetch_values('a', 'c') { |key| 'z' } # => ["x", "z"]
hash.fetch_values('a', 'b') # => ["x", "y"]
hash[:b] = 'y'
hash[:a] = 'x'
hash = ActiveSupport::HashWithIndifferentAccess.new

raises an exception when one of the keys can't be found.
Returns an array of the values at the specified indices, but also
def fetch_values(*indices, &block)
  super(*indices.map { |key| convert_key(key) }, &block)
end

def initialize(constructor = nil)

def initialize(constructor = nil)
  if constructor.respond_to?(:to_hash)
    super()
    update(constructor)
    hash = constructor.is_a?(Hash) ? constructor : constructor.to_hash
    self.default = hash.default if hash.default
    self.default_proc = hash.default_proc if hash.default_proc
  elsif constructor.nil?
    super()
  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(*hashes, &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(*hashes, &block)
  dup.update(*hashes, &block)
end

def nested_under_indifferent_access

def nested_under_indifferent_access
  self
end

def reject(*args, &block)

def reject(*args, &block)
  return to_enum(:reject) unless block_given?
  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(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(other_hash))
end

def reverse_merge!(other_hash)

Same semantics as +reverse_merge+ but modifies the receiver in-place.
def reverse_merge!(other_hash)
  super(self.class.new(other_hash))
end

def select(*args, &block)

def select(*args, &block)
  return to_enum(:select) unless block_given?
  dup.tap { |hash| hash.select!(*args, &block) }
end

def set_defaults(target)

def set_defaults(target)
  if default_proc
    target.default_proc = default_proc.dup
  else
    target.default = default
  end
end

def slice(*keys)

def slice(*keys)
  keys.map! { |key| convert_key(key) }
  self.class.new(super)
end

def slice!(*keys)

def slice!(*keys)
  keys.map! { |key| convert_key(key) }
  super
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 = Hash.new
  set_defaults(_new_hash)
  each do |key, value|
    _new_hash[key] = convert_value(value, conversion: :to_hash)
  end
  _new_hash
end

def to_options!; self end

def to_options!; self end

def transform_keys(*args, &block)

def transform_keys(*args, &block)
  return to_enum(:transform_keys) unless block_given?
  dup.tap { |hash| hash.transform_keys!(*args, &block) }
end

def transform_keys!

def transform_keys!
  return enum_for(:transform_keys!) { size } unless block_given?
  keys.each do |key|
    self[yield(key)] = delete(key)
  end
  self
end

def transform_values(*args, &block)

def transform_values(*args, &block)
  return to_enum(:transform_values) unless block_given?
  dup.tap { |hash| hash.transform_values!(*args, &block) }
end

def update(*other_hashes, &block)

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 arguments can be either an

hash.update({ "a" => 1 }, { "b" => 2 }) # => { "a" => 1, "b" => 2 }
hash = ActiveSupport::HashWithIndifferentAccess.new

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 hashes passed as arguments:
def update(*other_hashes, &block)
  if other_hashes.size == 1
    update_with_single_argument(other_hashes.first, block)
  else
    other_hashes.each do |other_hash|
      update_with_single_argument(other_hash, block)
    end
  end
  self
end

def update_with_single_argument(other_hash, block)

def update_with_single_argument(other_hash, block)
  if other_hash.is_a? HashWithIndifferentAccess
    regular_update(other_hash, &block)
  else
    other_hash.to_hash.each_pair do |key, value|
      if block && key?(key)
        value = block.call(convert_key(key), self[key], value)
      end
      regular_writer(convert_key(key), convert_value(value))
    end
  end
end

def values_at(*keys)

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(*keys)
  super(*keys.map { |key| convert_key(key) })
end

def with_indifferent_access

def with_indifferent_access
  dup
end