Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 172 lines (144 sloc) 4.538 kb
19cecc9 @spastorino HWIA relies on Hash#symbolize_keys and #stringify_keys extensions.
spastorino authored
1 require 'active_support/core_ext/hash/keys'
2
0bd668f @jeremy Namespace HashWithIndifferentAccess
jeremy authored
3 module ActiveSupport
7c90d91 @vijaydev Clean up module docs [ci skip]
vijaydev authored
4 # This class has dubious semantics and we only have it so that
5 # people can write <tt>params[:key]</tt> instead of <tt>params['key']</tt>
6 # and they get the same value for both keys.
0bd668f @jeremy Namespace HashWithIndifferentAccess
jeremy authored
7 class HashWithIndifferentAccess < Hash
c317c5b @tenderlove search private and protected methods for convert_key
tenderlove authored
8
1d3f833 @shawndrost document HashWithIndifferentAccess#extractable_options?
shawndrost authored
9 # Always returns true, so that <tt>Array#extract_options!</tt> finds members of this class.
a24a888 @wycats Limit Array#extract_options! to directl instances of Hash and HWIA. A…
wycats authored
10 def extractable_options?
11 true
12 end
13
94617d7 @dlee Optimize parts of HashWithIndifferentAccess
dlee authored
14 def with_indifferent_access
fb3ea8b @dlee Use dup to preserve previous behavior
dlee authored
15 dup
94617d7 @dlee Optimize parts of HashWithIndifferentAccess
dlee authored
16 end
17
3d6eafe @azimux Overrode Hash#nested_under_indifferent_access in HashWithIndifferentA…
azimux authored
18 def nested_under_indifferent_access
19 self
20 end
21
0bd668f @jeremy Namespace HashWithIndifferentAccess
jeremy authored
22 def initialize(constructor = {})
23 if constructor.is_a?(Hash)
24 super()
25 update(constructor)
26 else
27 super(constructor)
28 end
b4a1718 @jeremy Convert hash extension modules to class reopens
jeremy authored
29 end
30
0bd668f @jeremy Namespace HashWithIndifferentAccess
jeremy authored
31 def default(key = nil)
32 if key.is_a?(Symbol) && include?(key = key.to_s)
33 self[key]
34 else
35 super
36 end
b4a1718 @jeremy Convert hash extension modules to class reopens
jeremy authored
37 end
38
eab4860 @fxn avoids a ton o warnings activesupport/lib/active_support/dependencies…
fxn authored
39 def self.new_from_hash_copying_default(hash)
02039e9 @laserlemon Ensure that HashWithIndifferentAccess duplication preserves class (fo…
laserlemon authored
40 new(hash).tap do |new_hash|
eab4860 @fxn avoids a ton o warnings activesupport/lib/active_support/dependencies…
fxn authored
41 new_hash.default = hash.default
42 end
43 end
44
2ee28b2 @lest fix HashWithIndifferentAccess.[] method
lest authored
45 def self.[](*args)
46 new.merge(Hash[*args])
47 end
48
0bd668f @jeremy Namespace HashWithIndifferentAccess
jeremy authored
49 alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
50 alias_method :regular_update, :update unless method_defined?(:regular_update)
b4a1718 @jeremy Convert hash extension modules to class reopens
jeremy authored
51
0bd668f @jeremy Namespace HashWithIndifferentAccess
jeremy authored
52 # Assigns a new value to the hash:
53 #
54 # hash = HashWithIndifferentAccess.new
55 # hash[:key] = "value"
56 #
57 def []=(key, value)
58 regular_writer(convert_key(key), convert_value(value))
59 end
b4a1718 @jeremy Convert hash extension modules to class reopens
jeremy authored
60
d80afed @andreacampi Override #store to be consistent with #[].
andreacampi authored
61 alias_method :store, :[]=
62
0bd668f @jeremy Namespace HashWithIndifferentAccess
jeremy authored
63 # Updates the instantized hash with values from the second:
64 #
65 # hash_1 = HashWithIndifferentAccess.new
66 # hash_1[:key] = "value"
67 #
68 # hash_2 = HashWithIndifferentAccess.new
69 # hash_2[:key] = "New Value!"
70 #
71 # hash_1.update(hash_2) # => {"key"=>"New Value!"}
72 #
73 def update(other_hash)
94617d7 @dlee Optimize parts of HashWithIndifferentAccess
dlee authored
74 if other_hash.is_a? HashWithIndifferentAccess
75 super(other_hash)
76 else
77 other_hash.each_pair { |key, value| regular_writer(convert_key(key), convert_value(value)) }
78 self
79 end
0bd668f @jeremy Namespace HashWithIndifferentAccess
jeremy authored
80 end
b4a1718 @jeremy Convert hash extension modules to class reopens
jeremy authored
81
0bd668f @jeremy Namespace HashWithIndifferentAccess
jeremy authored
82 alias_method :merge!, :update
83
84 # Checks the hash for a key matching the argument passed in:
85 #
86 # hash = HashWithIndifferentAccess.new
87 # hash["key"] = "value"
88 # hash.key? :key # => true
89 # hash.key? "key" # => true
90 #
91 def key?(key)
92 super(convert_key(key))
93 end
b4a1718 @jeremy Convert hash extension modules to class reopens
jeremy authored
94
0bd668f @jeremy Namespace HashWithIndifferentAccess
jeremy authored
95 alias_method :include?, :key?
96 alias_method :has_key?, :key?
97 alias_method :member?, :key?
b4a1718 @jeremy Convert hash extension modules to class reopens
jeremy authored
98
0bd668f @jeremy Namespace HashWithIndifferentAccess
jeremy authored
99 # Fetches the value for the specified key, same as doing hash[key]
100 def fetch(key, *extras)
101 super(convert_key(key), *extras)
102 end
b4a1718 @jeremy Convert hash extension modules to class reopens
jeremy authored
103
0bd668f @jeremy Namespace HashWithIndifferentAccess
jeremy authored
104 # Returns an array of the values at the specified indices:
105 #
106 # hash = HashWithIndifferentAccess.new
107 # hash[:a] = "x"
108 # hash[:b] = "y"
109 # hash.values_at("a", "b") # => ["x", "y"]
110 #
111 def values_at(*indices)
112 indices.collect {|key| self[convert_key(key)]}
113 end
b4a1718 @jeremy Convert hash extension modules to class reopens
jeremy authored
114
0bd668f @jeremy Namespace HashWithIndifferentAccess
jeremy authored
115 # Returns an exact copy of the hash.
116 def dup
02039e9 @laserlemon Ensure that HashWithIndifferentAccess duplication preserves class (fo…
laserlemon authored
117 self.class.new(self).tap do |new_hash|
118 new_hash.default = default
119 end
0bd668f @jeremy Namespace HashWithIndifferentAccess
jeremy authored
120 end
b4a1718 @jeremy Convert hash extension modules to class reopens
jeremy authored
121
752d74f @vijaydev docs formatting changes
vijaydev authored
122 # Merges the instantized and the specified hashes together, giving precedence to the values from the second hash.
0bd668f @jeremy Namespace HashWithIndifferentAccess
jeremy authored
123 # Does not overwrite the existing hash.
124 def merge(hash)
125 self.dup.update(hash)
126 end
b4a1718 @jeremy Convert hash extension modules to class reopens
jeremy authored
127
0bd668f @jeremy Namespace HashWithIndifferentAccess
jeremy authored
128 # Performs the opposite of merge, with the keys and values from the first hash taking precedence over the second.
9b96de6 @suchasurge Some style changes
suchasurge authored
129 # This overloaded definition prevents returning a regular hash, if reverse_merge is called on a <tt>HashWithDifferentAccess</tt>.
0bd668f @jeremy Namespace HashWithIndifferentAccess
jeremy authored
130 def reverse_merge(other_hash)
5914875 @fxn now for real, the suite loads everything and these went unpatched
fxn authored
131 super self.class.new_from_hash_copying_default(other_hash)
0bd668f @jeremy Namespace HashWithIndifferentAccess
jeremy authored
132 end
b4a1718 @jeremy Convert hash extension modules to class reopens
jeremy authored
133
0920e69 @methodmissing ActiveSupport Hash optimizations [#2902 state:resolved]
methodmissing authored
134 def reverse_merge!(other_hash)
135 replace(reverse_merge( other_hash ))
136 end
137
0bd668f @jeremy Namespace HashWithIndifferentAccess
jeremy authored
138 # Removes a specified key from the hash.
139 def delete(key)
140 super(convert_key(key))
141 end
b4a1718 @jeremy Convert hash extension modules to class reopens
jeremy authored
142
d692e6b @jeremy Restore HWIA#stringify_keys! and update changelog
jeremy authored
143 def stringify_keys!; self end
c976784 @jeremy Change HWIA#stringify_keys to return a HWIA not a Hash
jeremy authored
144 def stringify_keys; dup end
2472f10 @spastorino HWIA delegates to to_hash symbolize_keys and stringify_keys and bang …
spastorino authored
145 undef :symbolize_keys!
146 def symbolize_keys; to_hash.symbolize_keys end
0bd668f @jeremy Namespace HashWithIndifferentAccess
jeremy authored
147 def to_options!; self end
b4a1718 @jeremy Convert hash extension modules to class reopens
jeremy authored
148
0bd668f @jeremy Namespace HashWithIndifferentAccess
jeremy authored
149 # Convert to a Hash with String keys.
150 def to_hash
0920e69 @methodmissing ActiveSupport Hash optimizations [#2902 state:resolved]
methodmissing authored
151 Hash.new(default).merge!(self)
b4a1718 @jeremy Convert hash extension modules to class reopens
jeremy authored
152 end
153
0bd668f @jeremy Namespace HashWithIndifferentAccess
jeremy authored
154 protected
155 def convert_key(key)
156 key.kind_of?(Symbol) ? key.to_s : key
b4a1718 @jeremy Convert hash extension modules to class reopens
jeremy authored
157 end
0bd668f @jeremy Namespace HashWithIndifferentAccess
jeremy authored
158
159 def convert_value(value)
099eb2b @dlee indifferent access should recurse Hash subclasses
dlee authored
160 if value.is_a? Hash
161 value.nested_under_indifferent_access
ce9456e @josevalim Only convert direct hash instances in hash with indifferent access.
josevalim authored
162 elsif value.is_a?(Array)
163 value.dup.replace(value.map { |e| convert_value(e) })
0bd668f @jeremy Namespace HashWithIndifferentAccess
jeremy authored
164 else
165 value
166 end
167 end
168 end
b4a1718 @jeremy Convert hash extension modules to class reopens
jeremy authored
169 end
0bd668f @jeremy Namespace HashWithIndifferentAccess
jeremy authored
170
171 HashWithIndifferentAccess = ActiveSupport::HashWithIndifferentAccess
Something went wrong with that request. Please try again.