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 self.new_from_hash_copying_default(hash)
def self.new_from_hash_copying_default(hash) ActiveSupport::Deprecation.warn(<<-MSG.squish) `ActiveSupport::HashWithIndifferentAccess.new_from_hash_copying_default` has been deprecated, and will be removed in Rails 5.1. The behavior of this method is now identical to the behavior of `.new`. MSG new(hash) end
def [](key)
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)
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 compact
def compact dup.tap(&:compact!) 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) if options[:for] != :assignment || value.frozen? 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(*args)
def default(*args) arg_key = args.first if include?(key = convert_key(arg_key)) self[key] else super end end
def delete(key)
def delete(key) super(convert_key(key)) end
def dup
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 extractable_options?
Returns +true+ so that Array#extract_options! finds members of
def extractable_options? true end
def fetch(key, *extras)
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.respond_to?(:to_hash) super() update(constructor) hash = constructor.to_hash self.default = hash.default if hash.default self.default_proc = hash.default_proc if hash.default_proc else super(constructor) end end
def key?(key)
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)
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) return to_enum(:reject) unless block_given? dup.tap { |hash| hash.reject!(*args, &block) } end
def replace(other_hash)
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['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)
def reverse_merge!(other_hash) replace(reverse_merge( 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 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
def to_hash _new_hash = Hash.new set_defaults(_new_hash) each do |key, value| _new_hash[key] = convert_value(value, for: :to_hash) end _new_hash end
def to_options!; self end
def to_options!; 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_hash)
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[: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