class ActiveSupport::HashWithIndifferentAccess - activesupport-4.2.4 Documentation

# class ActiveSupport::HashWithIndifferentAccess

Implements a hash where keys `:foo` and `"foo"` are considered to be the same.

    rgb = ActiveSupport::HashWithIndifferentAccess.new

    rgb[:black] = '#000000'
    rgb[:black]  # => '#000000'
    rgb['black'] # => '#000000'

    rgb['white'] = '#FFFFFF'
    rgb[:white]  # => '#FFFFFF'
    rgb['white'] # => '#FFFFFF'

Internally symbols are mapped to strings when used as keys in the entire writing interface (calling `[]=`, `merge`, etc). This mapping belongs to the public interface. For example, given:

    hash = ActiveSupport::HashWithIndifferentAccess.new(a: 1)

You are guaranteed that the key is returned as a string:

    hash.keys # => ["a"]

Technically other types of keys are accepted:

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

but this class is intended for use cases where strings or symbols are the expected keys and it is convenient to understand both as the same. For example the `params` hash in Ruby on Rails.

Note that core extensions define `Hash#with_indifferent_access`:

    rgb = { black: '#000000', white: '#FFFFFF' }.with_indifferent_access

which may be handy.

### Private Class Methods

[](*args) click to toggle source

    # File lib/active_support/hash_with_indifferent_access.rb, line 83
    def self.[](*args)
      new.merge!(Hash[*args])
    end

new(constructor = {}) click to toggle source
Calls superclass method

    # File lib/active_support/hash_with_indifferent_access.rb, line 58
    def initialize(constructor = {})
      if constructor.respond_to?(:to_hash)
        super()
        update(constructor)
      else
        super(constructor)
      end
    end

new_from_hash_copying_default(hash) click to toggle source

    # File lib/active_support/hash_with_indifferent_access.rb, line 75
    def self.new_from_hash_copying_default(hash)
      hash = hash.to_hash
      new(hash).tap do |new_hash|
        new_hash.default = hash.default
        new_hash.default_proc = hash.default_proc if hash.default_proc
      end
    end

### Private Instance Methods

[]=(key, value) click to toggle source

Assigns a new value to the hash:

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

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

    # File lib/active_support/hash_with_indifferent_access.rb, line 96
    def []=(key, value)
      regular_writer(convert_key(key), convert_value(value, for: :assignment))
    end

Also aliased as: regular_writer, store
convert_key(key) click to toggle source

    # File lib/active_support/hash_with_indifferent_access.rb, line 260
    def convert_key(key)
      key.kind_of?(Symbol) ? key.to_s : key
    end

convert_value(value, options = {}) click to toggle source

    # File lib/active_support/hash_with_indifferent_access.rb, line 264
    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

deep_stringify_keys() click to toggle source

    # File lib/active_support/hash_with_indifferent_access.rb, line 233
    def deep_stringify_keys; dup end

deep_stringify_keys!() click to toggle source

    # File lib/active_support/hash_with_indifferent_access.rb, line 231
    def deep_stringify_keys!; self end

deep_symbolize_keys() click to toggle source

    # File lib/active_support/hash_with_indifferent_access.rb, line 237
    def deep_symbolize_keys; to_hash.deep_symbolize_keys! end

default(key = nil) click to toggle source
Calls superclass method

    # File lib/active_support/hash_with_indifferent_access.rb, line 67
    def default(key = nil)
      if key.is_a?(Symbol) && include?(key = key.to_s)
        self[key]
      else
        super
      end
    end

delete(key) click to toggle source

Removes the specified key from the hash.

Calls superclass method

    # File lib/active_support/hash_with_indifferent_access.rb, line 226
    def delete(key)
      super(convert_key(key))
    end

dup() click to toggle source

Returns a shallow copy of the hash.

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

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

    # File lib/active_support/hash_with_indifferent_access.rb, line 189
    def dup
      self.class.new(self).tap do |new_hash|
        set_defaults(new_hash)
      end
    end

extractable_options?() click to toggle source

Returns `true` so that `Array#extract_options!` finds members of this class.

    # File lib/active_support/hash_with_indifferent_access.rb, line 46
    def extractable_options?
      true
    end

fetch(key, *extras) click to toggle source

Same as `Hash#fetch` where the key passed as argument can be either a string or a symbol:

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

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

Calls superclass method

    # File lib/active_support/hash_with_indifferent_access.rb, line 167
    def fetch(key, *extras)
      super(convert_key(key), *extras)
    end

has_key?(key)
Alias for: key?
include?(key)
Alias for: key?
key?(key) click to toggle source

Checks the hash for a key matching the argument passed in:

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

Calls superclass method

    # File lib/active_support/hash_with_indifferent_access.rb, line 149
    def key?(key)
      super(convert_key(key))
    end

Also aliased as: include?, has_key?, member?
member?(key)
Alias for: key?
merge(hash, &block) click to toggle source

This method has the same semantics of `update`, except it does not modify the receiver but rather returns a new hash with indifferent access with the result of the merge.

    # File lib/active_support/hash_with_indifferent_access.rb, line 198
    def merge(hash, &block)
      self.dup.update(hash, &block)
    end

merge!(other_hash)
Alias for: update
nested_under_indifferent_access() click to toggle source

    # File lib/active_support/hash_with_indifferent_access.rb, line 54
    def nested_under_indifferent_access
      self
    end

regular_update(other_hash)
Alias for: update
regular_writer(key, value)
Alias for: []=
reject(*args, &block) click to toggle source

    # File lib/active_support/hash_with_indifferent_access.rb, line 244
    def reject(*args, &block)
      dup.tap { |hash| hash.reject!(*args, &block) }
    end

replace(other_hash) click to toggle source

Replaces the contents of this hash with other_hash.

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

Calls superclass method

    # File lib/active_support/hash_with_indifferent_access.rb, line 221
    def replace(other_hash)
      super(self.class.new_from_hash_copying_default(other_hash))
    end

reverse_merge(other_hash) click to toggle source

Like `merge` but the other way around: Merges the receiver into the argument and returns a new hash with indifferent access as result:

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

Calls superclass method Hash#reverse_merge

    # File lib/active_support/hash_with_indifferent_access.rb, line 208
    def reverse_merge(other_hash)
      super(self.class.new_from_hash_copying_default(other_hash))
    end

reverse_merge!(other_hash) click to toggle source

Same semantics as `reverse_merge` but modifies the receiver in-place.

    # File lib/active_support/hash_with_indifferent_access.rb, line 213
    def reverse_merge!(other_hash)
      replace(reverse_merge( other_hash ))
    end

select(*args, &block) click to toggle source

    # File lib/active_support/hash_with_indifferent_access.rb, line 240
    def select(*args, &block)
      dup.tap { |hash| hash.select!(*args, &block) }
    end

set_defaults(target) click to toggle source

    # File lib/active_support/hash_with_indifferent_access.rb, line 281
    def set_defaults(target)
      if default_proc
        target.default_proc = default_proc.dup
      else
        target.default = default
      end
    end

store(key, value)
Alias for: []=
stringify_keys() click to toggle source

    # File lib/active_support/hash_with_indifferent_access.rb, line 232
    def stringify_keys; dup end

stringify_keys!() click to toggle source

    # File lib/active_support/hash_with_indifferent_access.rb, line 230
    def stringify_keys!; self end

symbolize_keys() click to toggle source

    # File lib/active_support/hash_with_indifferent_access.rb, line 236
    def symbolize_keys; to_hash.symbolize_keys! end

to_hash() click to toggle source

Convert to a regular hash with string keys.

    # File lib/active_support/hash_with_indifferent_access.rb, line 249
    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

to_options!() click to toggle source

    # File lib/active_support/hash_with_indifferent_access.rb, line 238
    def to_options!; self end

update(other_hash) { |convert_key(key), self, value| ... } click to toggle source

Updates the receiver in-place, merging in the hash passed as argument:

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

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

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

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

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

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

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

Calls superclass method

    # File lib/active_support/hash_with_indifferent_access.rb, line 127
    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

Also aliased as: regular_update, merge!
values_at(*indices) click to toggle source

Returns an array of the values at the specified indices:

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

    # File lib/active_support/hash_with_indifferent_access.rb, line 177
    def values_at(*indices)
      indices.collect { |key| self[convert_key(key)] }
    end

with_indifferent_access() click to toggle source

    # File lib/active_support/hash_with_indifferent_access.rb, line 50
    def with_indifferent_access
      dup
    end