hashie 4.0.0 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +213 -187
- data/CONTRIBUTING.md +13 -6
- data/README.md +33 -9
- data/UPGRADING.md +5 -5
- data/hashie.gemspec +11 -6
- data/lib/hashie.rb +1 -0
- data/lib/hashie/extensions/dash/property_translation.rb +1 -1
- data/lib/hashie/extensions/deep_merge.rb +18 -1
- data/lib/hashie/extensions/mash/permissive_respond_to.rb +61 -0
- data/lib/hashie/extensions/parsers/yaml_erb_parser.rb +19 -2
- data/lib/hashie/extensions/ruby_version_check.rb +5 -1
- data/lib/hashie/mash.rb +31 -26
- data/lib/hashie/utils.rb +28 -0
- data/lib/hashie/version.rb +1 -1
- metadata +16 -131
- data/spec/hashie/array_spec.rb +0 -29
- data/spec/hashie/clash_spec.rb +0 -70
- data/spec/hashie/dash_spec.rb +0 -608
- data/spec/hashie/extensions/autoload_spec.rb +0 -24
- data/spec/hashie/extensions/coercion_spec.rb +0 -648
- data/spec/hashie/extensions/dash/coercion_spec.rb +0 -13
- data/spec/hashie/extensions/dash/indifferent_access_spec.rb +0 -84
- data/spec/hashie/extensions/deep_fetch_spec.rb +0 -97
- data/spec/hashie/extensions/deep_find_spec.rb +0 -144
- data/spec/hashie/extensions/deep_locate_spec.rb +0 -138
- data/spec/hashie/extensions/deep_merge_spec.rb +0 -74
- data/spec/hashie/extensions/ignore_undeclared_spec.rb +0 -48
- data/spec/hashie/extensions/indifferent_access_spec.rb +0 -295
- data/spec/hashie/extensions/indifferent_access_with_rails_hwia_spec.rb +0 -208
- data/spec/hashie/extensions/key_conversion_spec.rb +0 -12
- data/spec/hashie/extensions/mash/define_accessors_spec.rb +0 -90
- data/spec/hashie/extensions/mash/keep_original_keys_spec.rb +0 -46
- data/spec/hashie/extensions/mash/safe_assignment_spec.rb +0 -50
- data/spec/hashie/extensions/mash/symbolize_keys_spec.rb +0 -39
- data/spec/hashie/extensions/merge_initializer_spec.rb +0 -23
- data/spec/hashie/extensions/method_access_spec.rb +0 -233
- data/spec/hashie/extensions/strict_key_access_spec.rb +0 -109
- data/spec/hashie/extensions/stringify_keys_spec.rb +0 -124
- data/spec/hashie/extensions/symbolize_keys_spec.rb +0 -131
- data/spec/hashie/hash_spec.rb +0 -123
- data/spec/hashie/mash_spec.rb +0 -1077
- data/spec/hashie/parsers/yaml_erb_parser_spec.rb +0 -46
- data/spec/hashie/rash_spec.rb +0 -83
- data/spec/hashie/trash_spec.rb +0 -334
- data/spec/hashie/utils_spec.rb +0 -25
- data/spec/hashie/version_spec.rb +0 -7
- data/spec/hashie_spec.rb +0 -13
- data/spec/integration/elasticsearch/integration_spec.rb +0 -41
- data/spec/integration/omniauth-oauth2/app.rb +0 -52
- data/spec/integration/omniauth-oauth2/integration_spec.rb +0 -26
- data/spec/integration/omniauth-oauth2/some_site.rb +0 -38
- data/spec/integration/omniauth/app.rb +0 -11
- data/spec/integration/omniauth/integration_spec.rb +0 -38
- data/spec/integration/rails-without-dependency/integration_spec.rb +0 -15
- data/spec/integration/rails/app.rb +0 -40
- data/spec/integration/rails/integration_spec.rb +0 -47
- data/spec/spec_helper.rb +0 -23
- data/spec/support/integration_specs.rb +0 -36
- data/spec/support/logger.rb +0 -24
- data/spec/support/module_context.rb +0 -11
- data/spec/support/ruby_version_check.rb +0 -6
@@ -1,74 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Hashie::Extensions::DeepMerge do
|
4
|
-
class DeepMergeHash < Hash
|
5
|
-
include Hashie::Extensions::DeepMerge
|
6
|
-
end
|
7
|
-
|
8
|
-
subject { DeepMergeHash }
|
9
|
-
|
10
|
-
it 'should return initial hash for arguments that are not hash' do
|
11
|
-
hash = subject.new.merge(a: 'a')
|
12
|
-
expect(hash.deep_merge('abc')).to eq(hash)
|
13
|
-
end
|
14
|
-
|
15
|
-
context 'without &block' do
|
16
|
-
let(:h1) do
|
17
|
-
subject.new.merge(a: 'a', a1: 42, b: 'b', c: { c1: 'c1', c2: { a: 'b' }, c3: { d1: 'd1' } })
|
18
|
-
end
|
19
|
-
let(:h2) { { a: 1, a1: 1, c: { c1: 2, c2: 'c2', c3: { d2: 'd2' } }, e: { e1: 1 } } }
|
20
|
-
let(:expected_hash) do
|
21
|
-
{ a: 1, a1: 1, b: 'b', c: { c1: 2, c2: 'c2', c3: { d1: 'd1', d2: 'd2' } }, e: { e1: 1 } }
|
22
|
-
end
|
23
|
-
|
24
|
-
it 'deep merges two hashes' do
|
25
|
-
expect(h1.deep_merge(h2)).to eq expected_hash
|
26
|
-
end
|
27
|
-
|
28
|
-
it 'deep merges another hash in place via bang method' do
|
29
|
-
h1.deep_merge!(h2)
|
30
|
-
expect(h1).to eq expected_hash
|
31
|
-
end
|
32
|
-
|
33
|
-
it 'merges new nested hash entries by value, not by reference' do
|
34
|
-
h1.deep_merge!(h2)
|
35
|
-
expect { h1[:e][:e1] = 'changed' }.not_to(change { h2[:e][:e1] })
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
context 'with &block' do
|
40
|
-
let(:h1) { subject.new.merge(a: 100, b: 200, c: { c1: 100 }) }
|
41
|
-
let(:h2) { { b: 250, c: { c1: 200 } } }
|
42
|
-
let(:expected_hash) { { a: 100, b: 450, c: { c1: 300 } } }
|
43
|
-
let(:block) { proc { |_, this_val, other_val| this_val + other_val } }
|
44
|
-
|
45
|
-
it 'deep merges two hashes' do
|
46
|
-
expect(h1.deep_merge(h2, &block)).to eq expected_hash
|
47
|
-
end
|
48
|
-
|
49
|
-
it 'deep merges another hash in place via bang method' do
|
50
|
-
h1.deep_merge!(h2, &block)
|
51
|
-
expect(h1).to eq expected_hash
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
context 'from extended object' do
|
56
|
-
subject { Hash }
|
57
|
-
let(:h1) { subject.new.merge(a: 100, c: { c1: 100 }).extend(Hashie::Extensions::DeepMerge) }
|
58
|
-
let(:h2) { { b: 250, c: { c1: 200 } } }
|
59
|
-
let(:expected_hash) { { a: 100, b: 250, c: { c1: 200 } } }
|
60
|
-
|
61
|
-
it 'does not raise error' do
|
62
|
-
expect { h1.deep_merge(h2) } .not_to raise_error
|
63
|
-
end
|
64
|
-
|
65
|
-
it 'deep merges two hashes' do
|
66
|
-
expect(h1.deep_merge(h2)).to eq expected_hash
|
67
|
-
end
|
68
|
-
|
69
|
-
it 'deep merges another hash in place via bang method' do
|
70
|
-
h1.deep_merge!(h2)
|
71
|
-
expect(h1).to eq expected_hash
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
@@ -1,48 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Hashie::Extensions::IgnoreUndeclared do
|
4
|
-
context 'included in Trash' do
|
5
|
-
class ForgivingTrash < Hashie::Trash
|
6
|
-
include Hashie::Extensions::IgnoreUndeclared
|
7
|
-
property :city
|
8
|
-
property :state, from: :provence
|
9
|
-
property :str_state, from: 'str_provence'
|
10
|
-
end
|
11
|
-
|
12
|
-
subject { ForgivingTrash }
|
13
|
-
|
14
|
-
it 'silently ignores undeclared properties on initialization' do
|
15
|
-
expect { subject.new(city: 'Toronto', provence: 'ON', country: 'Canada') }.to_not raise_error
|
16
|
-
end
|
17
|
-
|
18
|
-
it 'works with translated properties (with symbol keys)' do
|
19
|
-
expect(subject.new(provence: 'Ontario').state).to eq('Ontario')
|
20
|
-
end
|
21
|
-
|
22
|
-
it 'works with translated properties (with string keys)' do
|
23
|
-
expect(subject.new('str_provence' => 'Ontario').str_state).to eq('Ontario')
|
24
|
-
end
|
25
|
-
|
26
|
-
it 'requires properties to be declared on assignment' do
|
27
|
-
hash = subject.new(city: 'Toronto')
|
28
|
-
expect { hash.country = 'Canada' }.to raise_error(NoMethodError)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
context 'combined with DeepMerge' do
|
33
|
-
class ForgivingTrashWithMerge < Hashie::Trash
|
34
|
-
include Hashie::Extensions::DeepMerge
|
35
|
-
include Hashie::Extensions::IgnoreUndeclared
|
36
|
-
property :some_key
|
37
|
-
end
|
38
|
-
|
39
|
-
it 'deep merges' do
|
40
|
-
class ForgivingTrashWithMergeAndProperty < ForgivingTrashWithMerge
|
41
|
-
property :some_other_key
|
42
|
-
end
|
43
|
-
hash = ForgivingTrashWithMergeAndProperty.new(some_ignored_key: 17, some_key: 12)
|
44
|
-
expect(hash.deep_merge(some_other_key: 55, some_ignored_key: 18))
|
45
|
-
.to eq(some_key: 12, some_other_key: 55)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
@@ -1,295 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Hashie::Extensions::IndifferentAccess do
|
4
|
-
class IndifferentHashWithMergeInitializer < Hash
|
5
|
-
include Hashie::Extensions::MergeInitializer
|
6
|
-
include Hashie::Extensions::IndifferentAccess
|
7
|
-
|
8
|
-
class << self
|
9
|
-
alias build new
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
class IndifferentHashWithArrayInitializer < Hash
|
14
|
-
include Hashie::Extensions::IndifferentAccess
|
15
|
-
|
16
|
-
class << self
|
17
|
-
alias build []
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
class IndifferentHashWithTryConvertInitializer < Hash
|
22
|
-
include Hashie::Extensions::IndifferentAccess
|
23
|
-
|
24
|
-
class << self
|
25
|
-
alias build try_convert
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
class IndifferentHashWithDash < Hashie::Dash
|
30
|
-
include Hashie::Extensions::IndifferentAccess
|
31
|
-
property :foo
|
32
|
-
end
|
33
|
-
|
34
|
-
class IndifferentHashWithIgnoreUndeclaredAndPropertyTranslation < Hashie::Dash
|
35
|
-
include Hashie::Extensions::IgnoreUndeclared
|
36
|
-
include Hashie::Extensions::Dash::PropertyTranslation
|
37
|
-
include Hashie::Extensions::IndifferentAccess
|
38
|
-
property :foo, from: :bar
|
39
|
-
end
|
40
|
-
|
41
|
-
describe '#merge' do
|
42
|
-
it 'indifferently merges in a hash' do
|
43
|
-
indifferent_hash = Class.new(::Hash) do
|
44
|
-
include Hashie::Extensions::IndifferentAccess
|
45
|
-
end.new
|
46
|
-
|
47
|
-
merged_hash = indifferent_hash.merge(cat: 'meow')
|
48
|
-
|
49
|
-
expect(merged_hash[:cat]).to eq('meow')
|
50
|
-
expect(merged_hash['cat']).to eq('meow')
|
51
|
-
end
|
52
|
-
|
53
|
-
it 'injects the resulting new Hash with IndifferentAccess' do
|
54
|
-
hash = IndifferentHashWithMergeInitializer.new(
|
55
|
-
:cat => 'meow',
|
56
|
-
'dog' => { name: 'Mango', sound: 'woof' }
|
57
|
-
)
|
58
|
-
|
59
|
-
dog = hash[:dog]
|
60
|
-
merged = dog.merge(foo: 'bar')
|
61
|
-
|
62
|
-
expect(merged[:foo]).to eq('bar')
|
63
|
-
expect(merged['foo']).to eq('bar')
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
describe '#merge!' do
|
68
|
-
it 'indifferently merges in a hash' do
|
69
|
-
indifferent_hash = Class.new(::Hash) do
|
70
|
-
include Hashie::Extensions::IndifferentAccess
|
71
|
-
end.new
|
72
|
-
|
73
|
-
indifferent_hash[:cat] = 'meow'
|
74
|
-
|
75
|
-
expect(indifferent_hash[:cat]).to eq('meow')
|
76
|
-
expect(indifferent_hash['cat']).to eq('meow')
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
describe 'when included in dash' do
|
81
|
-
let(:params) { { foo: 'bar' } }
|
82
|
-
subject { IndifferentHashWithDash.new(params) }
|
83
|
-
|
84
|
-
it 'initialize with a symbol' do
|
85
|
-
expect(subject.foo).to eq params[:foo]
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
describe 'when translating properties and ignoring undeclared' do
|
90
|
-
let(:value) { 'baz' }
|
91
|
-
|
92
|
-
subject { IndifferentHashWithIgnoreUndeclaredAndPropertyTranslation.new(params) }
|
93
|
-
|
94
|
-
context 'and the hash keys are strings' do
|
95
|
-
let(:params) { { 'bar' => value } }
|
96
|
-
|
97
|
-
it 'sets the property' do
|
98
|
-
expect(subject[:foo]).to eq value
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
context 'and the hash keys are symbols' do
|
103
|
-
let(:params) { { bar: 'baz' } }
|
104
|
-
|
105
|
-
it 'sets the property' do
|
106
|
-
expect(subject[:foo]).to eq value
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
context 'and there are undeclared keys' do
|
111
|
-
let(:params) { { 'bar' => 'baz', 'fail' => false } }
|
112
|
-
|
113
|
-
it 'sets the property' do
|
114
|
-
expect(subject[:foo]).to eq value
|
115
|
-
end
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
shared_examples_for 'hash with indifferent access' do
|
120
|
-
it 'is able to access via string or symbol' do
|
121
|
-
h = subject.build(abc: 123)
|
122
|
-
expect(h[:abc]).to eq 123
|
123
|
-
expect(h['abc']).to eq 123
|
124
|
-
end
|
125
|
-
|
126
|
-
describe '#values_at' do
|
127
|
-
it 'indifferently finds values' do
|
128
|
-
h = subject.build(:foo => 'bar', 'baz' => 'qux')
|
129
|
-
expect(h.values_at('foo', :baz)).to eq %w[bar qux]
|
130
|
-
end
|
131
|
-
|
132
|
-
it 'returns the same instance of the hash that was set' do
|
133
|
-
hash = {}
|
134
|
-
h = subject.build(foo: hash)
|
135
|
-
expect(h.values_at(:foo)[0]).to be(hash)
|
136
|
-
end
|
137
|
-
|
138
|
-
it 'returns the same instance of the array that was set' do
|
139
|
-
array = []
|
140
|
-
h = subject.build(foo: array)
|
141
|
-
expect(h.values_at(:foo)[0]).to be(array)
|
142
|
-
end
|
143
|
-
|
144
|
-
it 'returns the same instance of the string that was set' do
|
145
|
-
str = 'my string'
|
146
|
-
h = subject.build(foo: str)
|
147
|
-
expect(h.values_at(:foo)[0]).to be(str)
|
148
|
-
end
|
149
|
-
|
150
|
-
it 'returns the same instance of the object that was set' do
|
151
|
-
object = Object.new
|
152
|
-
h = subject.build(foo: object)
|
153
|
-
expect(h.values_at(:foo)[0]).to be(object)
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
describe '#fetch' do
|
158
|
-
it 'works like normal fetch, but indifferent' do
|
159
|
-
h = subject.build(foo: 'bar')
|
160
|
-
expect(h.fetch(:foo)).to eq h.fetch('foo')
|
161
|
-
expect(h.fetch(:foo)).to eq 'bar'
|
162
|
-
end
|
163
|
-
|
164
|
-
it 'returns the same instance of the hash that was set' do
|
165
|
-
hash = {}
|
166
|
-
h = subject.build(foo: hash)
|
167
|
-
expect(h.fetch(:foo)).to be(hash)
|
168
|
-
end
|
169
|
-
|
170
|
-
it 'returns the same instance of the array that was set' do
|
171
|
-
array = []
|
172
|
-
h = subject.build(foo: array)
|
173
|
-
expect(h.fetch(:foo)).to be(array)
|
174
|
-
end
|
175
|
-
|
176
|
-
it 'returns the same instance of the string that was set' do
|
177
|
-
str = 'my string'
|
178
|
-
h = subject.build(foo: str)
|
179
|
-
expect(h.fetch(:foo)).to be(str)
|
180
|
-
end
|
181
|
-
|
182
|
-
it 'returns the same instance of the object that was set' do
|
183
|
-
object = Object.new
|
184
|
-
h = subject.build(foo: object)
|
185
|
-
expect(h.fetch(:foo)).to be(object)
|
186
|
-
end
|
187
|
-
|
188
|
-
it 'yields with key name if key does not exists' do
|
189
|
-
h = subject.build(a: 0)
|
190
|
-
expect(h.fetch(:foo) { |key| ['default for', key] }).to eq ['default for', 'foo']
|
191
|
-
end
|
192
|
-
end
|
193
|
-
|
194
|
-
describe '#delete' do
|
195
|
-
it 'deletes indifferently' do
|
196
|
-
h = subject.build(:foo => 'bar', 'baz' => 'qux')
|
197
|
-
h.delete('foo')
|
198
|
-
h.delete(:baz)
|
199
|
-
expect(h).to be_empty
|
200
|
-
end
|
201
|
-
end
|
202
|
-
|
203
|
-
describe '#key?' do
|
204
|
-
let(:h) { subject.build(foo: 'bar') }
|
205
|
-
|
206
|
-
it 'finds it indifferently' do
|
207
|
-
expect(h).to be_key(:foo)
|
208
|
-
expect(h).to be_key('foo')
|
209
|
-
end
|
210
|
-
|
211
|
-
%w[include? member? has_key?].each do |key_alias|
|
212
|
-
it "is aliased as #{key_alias}" do
|
213
|
-
expect(h.send(key_alias.to_sym, :foo)).to be(true)
|
214
|
-
expect(h.send(key_alias.to_sym, 'foo')).to be(true)
|
215
|
-
end
|
216
|
-
end
|
217
|
-
end
|
218
|
-
|
219
|
-
describe '#update' do
|
220
|
-
let(:h) { subject.build(foo: 'bar') }
|
221
|
-
|
222
|
-
it 'allows keys to be indifferent still' do
|
223
|
-
h.update(baz: 'qux')
|
224
|
-
expect(h['foo']).to eq 'bar'
|
225
|
-
expect(h['baz']).to eq 'qux'
|
226
|
-
end
|
227
|
-
|
228
|
-
it 'recursively injects indifference into sub-hashes' do
|
229
|
-
h.update(baz: { qux: 'abc' })
|
230
|
-
expect(h['baz']['qux']).to eq 'abc'
|
231
|
-
end
|
232
|
-
|
233
|
-
it 'does not change the ancestors of the injected object class' do
|
234
|
-
h.update(baz: { qux: 'abc' })
|
235
|
-
expect({}).not_to be_respond_to(:indifferent_access?)
|
236
|
-
end
|
237
|
-
end
|
238
|
-
|
239
|
-
describe '#replace' do
|
240
|
-
let(:h) { subject.build(foo: 'bar').replace(bar: 'baz', hi: 'bye') }
|
241
|
-
|
242
|
-
it 'returns self' do
|
243
|
-
expect(h).to be_a(subject)
|
244
|
-
end
|
245
|
-
|
246
|
-
it 'removes old keys' do
|
247
|
-
[:foo, 'foo'].each do |k|
|
248
|
-
expect(h[k]).to be_nil
|
249
|
-
expect(h.key?(k)).to be_falsy
|
250
|
-
end
|
251
|
-
end
|
252
|
-
|
253
|
-
it 'creates new keys with indifferent access' do
|
254
|
-
[:bar, 'bar', :hi, 'hi'].each { |k| expect(h.key?(k)).to be_truthy }
|
255
|
-
expect(h[:bar]).to eq 'baz'
|
256
|
-
expect(h['bar']).to eq 'baz'
|
257
|
-
expect(h[:hi]).to eq 'bye'
|
258
|
-
expect(h['hi']).to eq 'bye'
|
259
|
-
end
|
260
|
-
end
|
261
|
-
|
262
|
-
describe '#try_convert' do
|
263
|
-
describe 'with conversion' do
|
264
|
-
let(:h) { subject.try_convert(foo: 'bar') }
|
265
|
-
|
266
|
-
it 'is a subject' do
|
267
|
-
expect(h).to be_a(subject)
|
268
|
-
end
|
269
|
-
end
|
270
|
-
|
271
|
-
describe 'without conversion' do
|
272
|
-
let(:h) { subject.try_convert('{ :foo => bar }') }
|
273
|
-
|
274
|
-
it 'is nil' do
|
275
|
-
expect(h).to be_nil
|
276
|
-
end
|
277
|
-
end
|
278
|
-
end
|
279
|
-
end
|
280
|
-
|
281
|
-
describe 'with merge initializer' do
|
282
|
-
subject { IndifferentHashWithMergeInitializer }
|
283
|
-
it_should_behave_like 'hash with indifferent access'
|
284
|
-
end
|
285
|
-
|
286
|
-
describe 'with array initializer' do
|
287
|
-
subject { IndifferentHashWithArrayInitializer }
|
288
|
-
it_should_behave_like 'hash with indifferent access'
|
289
|
-
end
|
290
|
-
|
291
|
-
describe 'with try convert initializer' do
|
292
|
-
subject { IndifferentHashWithTryConvertInitializer }
|
293
|
-
it_should_behave_like 'hash with indifferent access'
|
294
|
-
end
|
295
|
-
end
|
@@ -1,208 +0,0 @@
|
|
1
|
-
# This set of tests verifies that Hashie::Extensions::IndifferentAccess works with
|
2
|
-
# ActiveSupport HashWithIndifferentAccess hashes. See #164 and #166 for details.
|
3
|
-
|
4
|
-
require 'active_support/hash_with_indifferent_access'
|
5
|
-
require 'active_support/core_ext/hash'
|
6
|
-
require 'spec_helper'
|
7
|
-
|
8
|
-
describe Hashie::Extensions::IndifferentAccess do
|
9
|
-
class IndifferentHashWithMergeInitializer < Hash
|
10
|
-
include Hashie::Extensions::MergeInitializer
|
11
|
-
include Hashie::Extensions::IndifferentAccess
|
12
|
-
|
13
|
-
class << self
|
14
|
-
alias build new
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
class IndifferentHashWithArrayInitializer < Hash
|
19
|
-
include Hashie::Extensions::IndifferentAccess
|
20
|
-
|
21
|
-
class << self
|
22
|
-
alias build []
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
class IndifferentHashWithTryConvertInitializer < Hash
|
27
|
-
include Hashie::Extensions::IndifferentAccess
|
28
|
-
|
29
|
-
class << self
|
30
|
-
alias build try_convert
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
class CoercableHash < Hash
|
35
|
-
include Hashie::Extensions::Coercion
|
36
|
-
include Hashie::Extensions::MergeInitializer
|
37
|
-
end
|
38
|
-
|
39
|
-
class MashWithIndifferentAccess < Hashie::Mash
|
40
|
-
include Hashie::Extensions::IndifferentAccess
|
41
|
-
end
|
42
|
-
|
43
|
-
shared_examples_for 'hash with indifferent access' do
|
44
|
-
it 'is able to access via string or symbol' do
|
45
|
-
indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(abc: 123)
|
46
|
-
h = subject.build(indifferent_hash)
|
47
|
-
expect(h[:abc]).to eq 123
|
48
|
-
expect(h['abc']).to eq 123
|
49
|
-
end
|
50
|
-
|
51
|
-
describe '#values_at' do
|
52
|
-
it 'indifferently finds values' do
|
53
|
-
indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(
|
54
|
-
:foo => 'bar', 'baz' => 'qux'
|
55
|
-
)
|
56
|
-
h = subject.build(indifferent_hash)
|
57
|
-
expect(h.values_at('foo', :baz)).to eq %w[bar qux]
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
describe '#fetch' do
|
62
|
-
it 'works like normal fetch, but indifferent' do
|
63
|
-
indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(foo: 'bar')
|
64
|
-
h = subject.build(indifferent_hash)
|
65
|
-
expect(h.fetch(:foo)).to eq h.fetch('foo')
|
66
|
-
expect(h.fetch(:foo)).to eq 'bar'
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
describe '#delete' do
|
71
|
-
it 'deletes indifferently' do
|
72
|
-
indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(
|
73
|
-
:foo => 'bar',
|
74
|
-
'baz' => 'qux'
|
75
|
-
)
|
76
|
-
h = subject.build(indifferent_hash)
|
77
|
-
h.delete('foo')
|
78
|
-
h.delete(:baz)
|
79
|
-
expect(h).to be_empty
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
describe '#key?' do
|
84
|
-
let(:h) do
|
85
|
-
indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(foo: 'bar')
|
86
|
-
subject.build(indifferent_hash)
|
87
|
-
end
|
88
|
-
|
89
|
-
it 'finds it indifferently' do
|
90
|
-
expect(h).to be_key(:foo)
|
91
|
-
expect(h).to be_key('foo')
|
92
|
-
end
|
93
|
-
|
94
|
-
%w[include? member? has_key?].each do |key_alias|
|
95
|
-
it "is aliased as #{key_alias}" do
|
96
|
-
expect(h.send(key_alias.to_sym, :foo)).to be(true)
|
97
|
-
expect(h.send(key_alias.to_sym, 'foo')).to be(true)
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
describe '#update' do
|
103
|
-
let(:h) do
|
104
|
-
indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(foo: 'bar')
|
105
|
-
subject.build(indifferent_hash)
|
106
|
-
end
|
107
|
-
|
108
|
-
it 'allows keys to be indifferent still' do
|
109
|
-
h.update(baz: 'qux')
|
110
|
-
expect(h['foo']).to eq 'bar'
|
111
|
-
expect(h['baz']).to eq 'qux'
|
112
|
-
end
|
113
|
-
|
114
|
-
it 'recursively injects indifference into sub-hashes' do
|
115
|
-
h.update(baz: { qux: 'abc' })
|
116
|
-
expect(h['baz']['qux']).to eq 'abc'
|
117
|
-
end
|
118
|
-
|
119
|
-
it 'does not change the ancestors of the injected object class' do
|
120
|
-
h.update(baz: { qux: 'abc' })
|
121
|
-
expect({}).not_to be_respond_to(:indifferent_access?)
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
describe '#replace' do
|
126
|
-
let(:h) do
|
127
|
-
indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(foo: 'bar')
|
128
|
-
subject.build(indifferent_hash).replace(bar: 'baz', hi: 'bye')
|
129
|
-
end
|
130
|
-
|
131
|
-
it 'returns self' do
|
132
|
-
expect(h).to be_a(subject)
|
133
|
-
end
|
134
|
-
|
135
|
-
it 'removes old keys' do
|
136
|
-
[:foo, 'foo'].each do |k|
|
137
|
-
expect(h[k]).to be_nil
|
138
|
-
expect(h.key?(k)).to be_falsy
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
it 'creates new keys with indifferent access' do
|
143
|
-
[:bar, 'bar', :hi, 'hi'].each { |k| expect(h.key?(k)).to be_truthy }
|
144
|
-
expect(h[:bar]).to eq 'baz'
|
145
|
-
expect(h['bar']).to eq 'baz'
|
146
|
-
expect(h[:hi]).to eq 'bye'
|
147
|
-
expect(h['hi']).to eq 'bye'
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
describe '#try_convert' do
|
152
|
-
describe 'with conversion' do
|
153
|
-
let(:h) do
|
154
|
-
indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(foo: 'bar')
|
155
|
-
subject.try_convert(indifferent_hash)
|
156
|
-
end
|
157
|
-
|
158
|
-
it 'is a subject' do
|
159
|
-
expect(h).to be_a(subject)
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
163
|
-
describe 'without conversion' do
|
164
|
-
let(:h) { subject.try_convert('{ :foo => bar }') }
|
165
|
-
|
166
|
-
it 'is nil' do
|
167
|
-
expect(h).to be_nil
|
168
|
-
end
|
169
|
-
end
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
describe 'with merge initializer' do
|
174
|
-
subject { IndifferentHashWithMergeInitializer }
|
175
|
-
it_should_behave_like 'hash with indifferent access'
|
176
|
-
end
|
177
|
-
|
178
|
-
describe 'with array initializer' do
|
179
|
-
subject { IndifferentHashWithArrayInitializer }
|
180
|
-
it_should_behave_like 'hash with indifferent access'
|
181
|
-
end
|
182
|
-
|
183
|
-
describe 'with try convert initializer' do
|
184
|
-
subject { IndifferentHashWithTryConvertInitializer }
|
185
|
-
it_should_behave_like 'hash with indifferent access'
|
186
|
-
end
|
187
|
-
|
188
|
-
describe 'with coercion' do
|
189
|
-
subject { CoercableHash }
|
190
|
-
|
191
|
-
let(:instance) { subject.new }
|
192
|
-
|
193
|
-
it 'supports coercion for ActiveSupport::HashWithIndifferentAccess' do
|
194
|
-
subject.coerce_key :foo, ActiveSupport::HashWithIndifferentAccess.new(Coercable => Coercable)
|
195
|
-
instance[:foo] = { 'bar_key' => 'bar_value', 'bar2_key' => 'bar2_value' }
|
196
|
-
expect(instance[:foo].keys).to all(be_coerced)
|
197
|
-
expect(instance[:foo].values).to all(be_coerced)
|
198
|
-
expect(instance[:foo]).to be_a(ActiveSupport::HashWithIndifferentAccess)
|
199
|
-
end
|
200
|
-
end
|
201
|
-
|
202
|
-
describe 'Mash with indifferent access' do
|
203
|
-
it 'is able to be created for a deep nested HashWithIndifferentAccess' do
|
204
|
-
indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(abc: { def: 123 })
|
205
|
-
MashWithIndifferentAccess.new(indifferent_hash)
|
206
|
-
end
|
207
|
-
end
|
208
|
-
end
|