module Hashie::Extensions::IndifferentAccess

IndifferentAccess gives you the ability to not care whether your hash has string or symbol keys. Made famous in Rails for accessing query and POST parameters, this is a handy tool for making sure your hash has maximum utility.

One unique feature of this mixin is that it will recursively inject itself into sub-hash instances without modifying the actual class of the sub-hash.

@example

class MyHash < Hash
  include Hashie::Extensions::MergeInitializer
  include Hashie::Extensions::IndifferentAccess
end

h = MyHash.new(:foo => 'bar', 'baz' => 'blip')
h['foo'] # => 'bar'
h[:foo]  # => 'bar'
h[:baz]  # => 'blip'
h['baz'] # => 'blip'

Public Class Methods

[](*) click to toggle source
Calls superclass method
# File lib/hashie/extensions/indifferent_access.rb, line 50
def [](*)
  super.convert!
end
convert_key(key) click to toggle source

@api private

# File lib/hashie/extensions/indifferent_access.rb, line 29
def self.convert_key(key)
  key.to_s
end
included(base) click to toggle source
# File lib/hashie/extensions/indifferent_access.rb, line 33
def self.included(base)
  Hashie::Extensions::Dash::IndifferentAccess.maybe_extend(base)

  base.class_eval do
    alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
    alias_method :[]=, :indifferent_writer
    alias_method :store, :indifferent_writer
    %w[default update replace fetch delete key? values_at].each do |m|
      alias_method "regular_#{m}", m unless method_defined?("regular_#{m}")
      alias_method m, "indifferent_#{m}"
    end

    %w[include? member? has_key?].each do |key_alias|
      alias_method key_alias, :indifferent_key?
    end

    class << self
      def [](*)
        super.convert!
      end

      def try_convert(*)
        (hash = super) && self[hash]
      end
    end
  end
end
inject(hash) click to toggle source

Injects indifferent access into a duplicate of the hash provided. See inject!

# File lib/hashie/extensions/indifferent_access.rb, line 71
def self.inject(hash)
  inject!(hash.dup)
end
inject!(hash) click to toggle source

This will inject indifferent access into an instance of a hash without modifying the actual class. This is what allows IndifferentAccess to spread to sub-hashes.

# File lib/hashie/extensions/indifferent_access.rb, line 64
def self.inject!(hash)
  (class << hash; self; end).send :include, IndifferentAccess
  hash.convert!
end
try_convert(*) click to toggle source
Calls superclass method
# File lib/hashie/extensions/indifferent_access.rb, line 54
def try_convert(*)
  (hash = super) && self[hash]
end

Public Instance Methods

convert!() click to toggle source

Iterates through the keys and values, reconverting them to their proper indifferent state. Used when IndifferentAccess is injecting itself into member hashes.

# File lib/hashie/extensions/indifferent_access.rb, line 82
def convert!
  keys.each do |k| # rubocop:disable Performance/HashEachMethods
    indifferent_writer k, regular_delete(k)
  end
  self
end
convert_key(key) click to toggle source
# File lib/hashie/extensions/indifferent_access.rb, line 75
def convert_key(key)
  IndifferentAccess.convert_key(key)
end
except(*keys) click to toggle source
Calls superclass method
# File lib/hashie/extensions/indifferent_access.rb, line 171
def except(*keys)
  string_keys = keys.map { |key| convert_key(key) }
  super(*string_keys)
end
indifferent_access?() click to toggle source
# File lib/hashie/extensions/indifferent_access.rb, line 131
def indifferent_access?
  true
end
indifferent_default(key = nil) click to toggle source
# File lib/hashie/extensions/indifferent_access.rb, line 99
def indifferent_default(key = nil)
  return self[convert_key(key)] if key?(key)
  regular_default(key)
end
indifferent_delete(key) click to toggle source
# File lib/hashie/extensions/indifferent_access.rb, line 119
def indifferent_delete(key)
  regular_delete convert_key(key)
end
indifferent_fetch(key, *args, &block) click to toggle source
# File lib/hashie/extensions/indifferent_access.rb, line 115
def indifferent_fetch(key, *args, &block)
  regular_fetch convert_key(key), *args, &block
end
indifferent_key?(key) click to toggle source
# File lib/hashie/extensions/indifferent_access.rb, line 123
def indifferent_key?(key)
  regular_key? convert_key(key)
end
indifferent_replace(other_hash) click to toggle source
# File lib/hashie/extensions/indifferent_access.rb, line 135
def indifferent_replace(other_hash)
  (keys - other_hash.keys).each { |key| delete(key) }
  other_hash.each { |key, value| self[key] = value }
  self
end
indifferent_update(other_hash) click to toggle source
# File lib/hashie/extensions/indifferent_access.rb, line 104
def indifferent_update(other_hash)
  return regular_update(other_hash) if hash_with_indifference?(other_hash)
  other_hash.each_pair do |k, v|
    self[k] = v
  end
end
indifferent_value(value) click to toggle source
# File lib/hashie/extensions/indifferent_access.rb, line 89
def indifferent_value(value)
  if hash_lacking_indifference?(value)
    IndifferentAccess.inject!(value)
  elsif value.is_a?(::Array)
    value.replace(value.map { |e| indifferent_value(e) })
  else
    value
  end
end
indifferent_values_at(*indices) click to toggle source
# File lib/hashie/extensions/indifferent_access.rb, line 127
def indifferent_values_at(*indices)
  indices.map { |i| self[i] }
end
indifferent_writer(key, value) click to toggle source
# File lib/hashie/extensions/indifferent_access.rb, line 111
def indifferent_writer(key, value)
  regular_writer convert_key(key), indifferent_value(value)
end
merge(*args) click to toggle source
Calls superclass method
# File lib/hashie/extensions/indifferent_access.rb, line 141
def merge(*args)
  result = super
  return IndifferentAccess.inject!(result) if hash_lacking_indifference?(result)
  result.convert!
end
merge!(*) click to toggle source
Calls superclass method
# File lib/hashie/extensions/indifferent_access.rb, line 147
def merge!(*)
  super.convert!
end
slice(*keys) click to toggle source
Calls superclass method
# File lib/hashie/extensions/indifferent_access.rb, line 164
def slice(*keys)
  string_keys = keys.map { |key| convert_key(key) }
  super(*string_keys)
end
to_hash() click to toggle source
# File lib/hashie/extensions/indifferent_access.rb, line 151
def to_hash
  {}.tap do |result|
    each_pair { |key, value| result[key] = value }

    if default_proc
      result.default_proc = default_proc
    else
      result.default = default
    end
  end
end

Protected Instance Methods

hash_lacking_indifference?(other) click to toggle source
# File lib/hashie/extensions/indifferent_access.rb, line 179
def hash_lacking_indifference?(other)
  other.is_a?(::Hash) &&
    !(other.respond_to?(:indifferent_access?) &&
      other.indifferent_access?)
end
hash_with_indifference?(other) click to toggle source
# File lib/hashie/extensions/indifferent_access.rb, line 185
def hash_with_indifference?(other)
  other.is_a?(::Hash) &&
    other.respond_to?(:indifferent_access?) &&
    other.indifferent_access?
end