Module: Hashie::Extensions::IndifferentAccess

Includes:
RubyVersionCheck
Defined in:
lib/hashie/extensions/indifferent_access.rb

Overview

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.

Examples:

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'

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.convert_key(key) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.


29
30
31
# File 'lib/hashie/extensions/indifferent_access.rb', line 29

def self.convert_key(key)
  key.to_s
end

.included(base) ⇒ Object


33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# 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) ⇒ Object

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


71
72
73
# File 'lib/hashie/extensions/indifferent_access.rb', line 71

def self.inject(hash)
  inject!(hash.dup)
end

.inject!(hash) ⇒ Object

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.


64
65
66
67
# File 'lib/hashie/extensions/indifferent_access.rb', line 64

def self.inject!(hash)
  (class << hash; self; end).send :include, IndifferentAccess
  hash.convert!
end

Instance Method Details

#convert!Object

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


82
83
84
85
86
87
# 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) ⇒ Object


75
76
77
# File 'lib/hashie/extensions/indifferent_access.rb', line 75

def convert_key(key)
  IndifferentAccess.convert_key(key)
end

#indifferent_access?Boolean

Returns:

  • (Boolean)

131
132
133
# File 'lib/hashie/extensions/indifferent_access.rb', line 131

def indifferent_access?
  true
end

#indifferent_default(key = nil) ⇒ Object


99
100
101
102
# 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) ⇒ Object


119
120
121
# File 'lib/hashie/extensions/indifferent_access.rb', line 119

def indifferent_delete(key)
  regular_delete convert_key(key)
end

#indifferent_fetch(key, *args, &block) ⇒ Object


115
116
117
# 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) ⇒ Boolean

Returns:

  • (Boolean)

123
124
125
# File 'lib/hashie/extensions/indifferent_access.rb', line 123

def indifferent_key?(key)
  regular_key? convert_key(key)
end

#indifferent_replace(other_hash) ⇒ Object


135
136
137
138
139
# 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) ⇒ Object


104
105
106
107
108
109
# 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) ⇒ Object


89
90
91
92
93
94
95
96
97
# 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) ⇒ Object


127
128
129
# File 'lib/hashie/extensions/indifferent_access.rb', line 127

def indifferent_values_at(*indices)
  indices.map { |i| self[i] }
end

#indifferent_writer(key, value) ⇒ Object


111
112
113
# 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) ⇒ Object


141
142
143
144
145
# 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!Object


147
148
149
# File 'lib/hashie/extensions/indifferent_access.rb', line 147

def merge!(*)
  super.convert!
end

#to_hashObject


151
152
153
154
155
156
157
158
159
160
161
# 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