hashie 2.1.0 → 2.1.1
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 +5 -1
- data/lib/hashie/hash.rb +13 -3
- data/lib/hashie/version.rb +1 -1
- data/spec/hashie/clash_spec.rb +11 -11
- data/spec/hashie/dash_spec.rb +69 -60
- data/spec/hashie/extensions/coercion_spec.rb +22 -22
- data/spec/hashie/extensions/deep_fetch_spec.rb +7 -7
- data/spec/hashie/extensions/deep_merge_spec.rb +2 -2
- data/spec/hashie/extensions/indifferent_access_spec.rb +24 -24
- data/spec/hashie/extensions/key_conversion_spec.rb +14 -14
- data/spec/hashie/extensions/merge_initializer_spec.rb +4 -4
- data/spec/hashie/extensions/method_access_spec.rb +22 -22
- data/spec/hashie/hash_spec.rb +19 -7
- data/spec/hashie/mash_spec.rb +122 -123
- data/spec/hashie/rash_spec.rb +13 -13
- data/spec/hashie/trash_spec.rb +30 -30
- data/spec/hashie/version_spec.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 669a459e63fb50152c48b98abf0bce58e5e138e5
|
4
|
+
data.tar.gz: 49b29974978742dab0b2c228dd2c473df1d89732
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 513d09bc3690cfa9a3913354c80bb9bb34321013ba46a710c8a4649ff3967218f4ed04a45bb79451623fadc2d340bb174b260ab8f9b424733c2d16f334f1d9d6
|
7
|
+
data.tar.gz: aea99e5db0b7c58499b45b6ca806fe99bb94a4e8e5c74df22af74a56844104778ba8a328d8e024a7f090daceaf092ed0eb25ae1d302dc901f4b05268ec851756
|
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,8 @@
|
|
1
|
-
##
|
1
|
+
## 2.1.1 (4/12/2014)
|
2
|
+
|
3
|
+
* [#144](https://github.com/intridea/hashie/issues/144): Fixed regression invoking `to_hash` with no parameters - [@mbleigh](https://github.com/mbleigh).
|
4
|
+
|
5
|
+
## 2.1.0 (4/6/2014)
|
2
6
|
|
3
7
|
* [#134](https://github.com/intridea/hashie/pull/134): Add deep_fetch extension for nested access - [@tylerdooling](https://github.com/tylerdooling).
|
4
8
|
* Removed support for Ruby 1.8.7 - [@dblock](https://github.com/dblock).
|
data/lib/hashie/hash.rb
CHANGED
@@ -16,18 +16,28 @@ module Hashie
|
|
16
16
|
if self[k].is_a?(Array)
|
17
17
|
out[assignment_key] ||= []
|
18
18
|
self[k].each do |array_object|
|
19
|
-
out[assignment_key] << (Hash === array_object ? array_object
|
19
|
+
out[assignment_key] << (Hash === array_object ? flexibly_convert_to_hash(array_object, options) : array_object)
|
20
20
|
end
|
21
21
|
else
|
22
|
-
out[assignment_key] = Hash === self[k] ? self[k]
|
22
|
+
out[assignment_key] = Hash === self[k] ? flexibly_convert_to_hash(self[k], options) : self[k]
|
23
23
|
end
|
24
24
|
end
|
25
25
|
out
|
26
26
|
end
|
27
27
|
|
28
|
-
# The C
|
28
|
+
# The C generator for the json gem doesn't like mashies
|
29
29
|
def to_json(*args)
|
30
30
|
to_hash.to_json(*args)
|
31
31
|
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def flexibly_convert_to_hash(object, options = {})
|
36
|
+
if object.method(:to_hash).arity == 0
|
37
|
+
object.to_hash
|
38
|
+
else
|
39
|
+
object.to_hash(options)
|
40
|
+
end
|
41
|
+
end
|
32
42
|
end
|
33
43
|
end
|
data/lib/hashie/version.rb
CHANGED
data/spec/hashie/clash_spec.rb
CHANGED
@@ -5,44 +5,44 @@ describe Hashie::Clash do
|
|
5
5
|
|
6
6
|
it 'is able to set an attribute via method_missing' do
|
7
7
|
subject.foo('bar')
|
8
|
-
subject[:foo].
|
8
|
+
expect(subject[:foo]).to eq 'bar'
|
9
9
|
end
|
10
10
|
|
11
11
|
it 'is able to set multiple attributes' do
|
12
12
|
subject.foo('bar').baz('wok')
|
13
|
-
subject.
|
13
|
+
expect(subject).to eq(foo: 'bar', baz: 'wok')
|
14
14
|
end
|
15
15
|
|
16
16
|
it 'converts multiple arguments into an array' do
|
17
17
|
subject.foo(1, 2, 3)
|
18
|
-
subject[:foo].
|
18
|
+
expect(subject[:foo]).to eq [1, 2, 3]
|
19
19
|
end
|
20
20
|
|
21
21
|
it 'is able to use bang notation to create a new Clash on a key' do
|
22
22
|
subject.foo!
|
23
|
-
subject[:foo].
|
23
|
+
expect(subject[:foo]).to be_kind_of(Hashie::Clash)
|
24
24
|
end
|
25
25
|
|
26
26
|
it 'is able to chain onto the new Clash when using bang notation' do
|
27
27
|
subject.foo!.bar('abc').baz(123)
|
28
|
-
subject.
|
28
|
+
expect(subject).to eq(foo: { bar: 'abc', baz: 123 })
|
29
29
|
end
|
30
30
|
|
31
31
|
it 'is able to jump back up to the parent in the chain with #_end!' do
|
32
32
|
subject.foo!.bar('abc')._end!.baz(123)
|
33
|
-
subject.
|
33
|
+
expect(subject).to eq(foo: { bar: 'abc' }, baz: 123)
|
34
34
|
end
|
35
35
|
|
36
36
|
it 'merges rather than replaces existing keys' do
|
37
37
|
subject.where(abc: 'def').where(hgi: 123)
|
38
|
-
subject.
|
38
|
+
expect(subject).to eq(where: { abc: 'def', hgi: 123 })
|
39
39
|
end
|
40
40
|
|
41
41
|
it 'is able to replace all of its own keys with #replace' do
|
42
42
|
subject.foo(:bar).hello(:world)
|
43
|
-
subject.replace(baz: 123, hgi: 123).
|
44
|
-
subject.
|
45
|
-
subject[:foo].
|
46
|
-
subject[:hello].
|
43
|
+
expect(subject.replace(baz: 123, hgi: 123)).to eq(baz: 123, hgi: 123)
|
44
|
+
expect(subject).to eq(baz: 123, hgi: 123)
|
45
|
+
expect(subject[:foo]).to be_nil
|
46
|
+
expect(subject[:hello]).to be_nil
|
47
47
|
end
|
48
48
|
end
|
data/spec/hashie/dash_spec.rb
CHANGED
@@ -40,102 +40,108 @@ describe DashTest do
|
|
40
40
|
|
41
41
|
it('subclasses Hashie::Hash') { should respond_to(:to_mash) }
|
42
42
|
|
43
|
-
|
43
|
+
describe '#to_s' do
|
44
|
+
subject { super().to_s }
|
45
|
+
it { should eq '#<DashTest count=0 email="bob@example.com" first_name="Bob">' }
|
46
|
+
end
|
44
47
|
|
45
48
|
it 'lists all set properties in inspect' do
|
46
49
|
subject.first_name = 'Bob'
|
47
50
|
subject.email = 'bob@example.com'
|
48
|
-
subject.inspect.
|
51
|
+
expect(subject.inspect).to eq '#<DashTest count=0 email="bob@example.com" first_name="Bob">'
|
49
52
|
end
|
50
53
|
|
51
|
-
|
54
|
+
describe '#count' do
|
55
|
+
subject { super().count }
|
56
|
+
it { should be_zero }
|
57
|
+
end
|
52
58
|
|
53
59
|
it { should respond_to(:first_name) }
|
54
60
|
it { should respond_to(:first_name=) }
|
55
61
|
it { should_not respond_to(:nonexistent) }
|
56
62
|
|
57
63
|
it 'errors out for a non-existent property' do
|
58
|
-
|
64
|
+
expect { subject['nonexistent'] }.to raise_error(NoMethodError)
|
59
65
|
end
|
60
66
|
|
61
67
|
it 'errors out when attempting to set a required property to nil' do
|
62
|
-
|
68
|
+
expect { subject.first_name = nil }.to raise_error(ArgumentError)
|
63
69
|
end
|
64
70
|
|
65
71
|
context 'writing to properties' do
|
66
72
|
it 'fails writing a required property to nil' do
|
67
|
-
|
73
|
+
expect { subject.first_name = nil }.to raise_error(ArgumentError)
|
68
74
|
end
|
69
75
|
|
70
76
|
it 'fails writing a required property to nil using []=' do
|
71
|
-
|
77
|
+
expect { subject['first_name'] = nil }.to raise_error(ArgumentError)
|
72
78
|
end
|
73
79
|
|
74
80
|
it 'fails writing to a non-existent property using []=' do
|
75
|
-
|
81
|
+
expect { subject['nonexistent'] = 123 }.to raise_error(NoMethodError)
|
76
82
|
end
|
77
83
|
|
78
84
|
it 'works for an existing property using []=' do
|
79
85
|
subject['first_name'] = 'Bob'
|
80
|
-
subject['first_name'].
|
81
|
-
subject[:first_name].
|
86
|
+
expect(subject['first_name']).to eq 'Bob'
|
87
|
+
expect(subject[:first_name]).to eq 'Bob'
|
82
88
|
end
|
83
89
|
|
84
90
|
it 'works for an existing property using a method call' do
|
85
91
|
subject.first_name = 'Franklin'
|
86
|
-
subject.first_name.
|
92
|
+
expect(subject.first_name).to eq 'Franklin'
|
87
93
|
end
|
88
94
|
end
|
89
95
|
|
90
96
|
context 'reading from properties' do
|
91
97
|
it 'fails reading from a non-existent property using []' do
|
92
|
-
|
98
|
+
expect { subject['nonexistent'] }.to raise_error(NoMethodError)
|
93
99
|
end
|
94
100
|
|
95
101
|
it 'is able to retrieve properties through blocks' do
|
96
102
|
subject['first_name'] = 'Aiden'
|
97
103
|
value = nil
|
98
104
|
subject.[]('first_name') { |v| value = v }
|
99
|
-
value.
|
105
|
+
expect(value).to eq 'Aiden'
|
100
106
|
end
|
101
107
|
|
102
108
|
it 'is able to retrieve properties through blocks with method calls' do
|
103
109
|
subject['first_name'] = 'Frodo'
|
104
110
|
value = nil
|
105
111
|
subject.first_name { |v| value = v }
|
106
|
-
value.
|
112
|
+
expect(value).to eq 'Frodo'
|
107
113
|
end
|
108
114
|
end
|
109
115
|
|
110
116
|
context 'reading from deferred properties' do
|
111
117
|
it 'evaluates proc after initial read' do
|
112
|
-
DeferredTest.new['created_at'].
|
118
|
+
expect(DeferredTest.new['created_at']).to be_instance_of(Time)
|
113
119
|
end
|
114
120
|
|
115
121
|
it 'does not evalute proc after subsequent reads' do
|
116
122
|
deferred = DeferredTest.new
|
117
|
-
deferred['created_at'].object_id.
|
123
|
+
expect(deferred['created_at'].object_id).to eq deferred['created_at'].object_id
|
118
124
|
end
|
119
125
|
end
|
120
126
|
|
121
127
|
describe '#new' do
|
122
128
|
it 'fails with non-existent properties' do
|
123
|
-
|
129
|
+
expect { described_class.new(bork: '') }.to raise_error(NoMethodError)
|
124
130
|
end
|
125
131
|
|
126
132
|
it 'sets properties that it is able to' do
|
127
133
|
obj = described_class.new first_name: 'Michael'
|
128
|
-
obj.first_name.
|
134
|
+
expect(obj.first_name).to eq 'Michael'
|
129
135
|
end
|
130
136
|
|
131
137
|
it 'accepts nil' do
|
132
|
-
|
138
|
+
expect { DashNoRequiredTest.new(nil) }.not_to raise_error
|
133
139
|
end
|
134
140
|
|
135
141
|
it 'accepts block to define a global default' do
|
136
142
|
obj = described_class.new { |hash, key| key.to_s.upcase }
|
137
|
-
obj.first_name.
|
138
|
-
obj.count.
|
143
|
+
expect(obj.first_name).to eq 'FIRST_NAME'
|
144
|
+
expect(obj.count).to be_zero
|
139
145
|
end
|
140
146
|
|
141
147
|
it 'fails when required values are missing' do
|
@@ -146,20 +152,20 @@ describe DashTest do
|
|
146
152
|
obj1 = DashDefaultTest.new
|
147
153
|
obj1.aliases << 'El Rey'
|
148
154
|
obj2 = DashDefaultTest.new
|
149
|
-
obj2.aliases.
|
155
|
+
expect(obj2.aliases).not_to include 'El Rey'
|
150
156
|
end
|
151
157
|
end
|
152
158
|
|
153
159
|
describe '#merge' do
|
154
160
|
it 'creates a new instance of the Dash' do
|
155
161
|
new_dash = subject.merge(first_name: 'Robert')
|
156
|
-
subject.object_id.
|
162
|
+
expect(subject.object_id).not_to eq new_dash.object_id
|
157
163
|
end
|
158
164
|
|
159
165
|
it 'merges the given hash' do
|
160
166
|
new_dash = subject.merge(first_name: 'Robert', email: 'robert@example.com')
|
161
|
-
new_dash.first_name.
|
162
|
-
new_dash.email.
|
167
|
+
expect(new_dash.first_name).to eq 'Robert'
|
168
|
+
expect(new_dash.email).to eq 'robert@example.com'
|
163
169
|
end
|
164
170
|
|
165
171
|
it 'fails with non-existent properties' do
|
@@ -172,9 +178,9 @@ describe DashTest do
|
|
172
178
|
|
173
179
|
context 'given a block' do
|
174
180
|
it "sets merged key's values to the block's return value" do
|
175
|
-
subject.merge(first_name: 'Jim') do |key, oldval, newval|
|
181
|
+
expect(subject.merge(first_name: 'Jim') do |key, oldval, newval|
|
176
182
|
"#{key}: #{newval} #{oldval}"
|
177
|
-
end.first_name.
|
183
|
+
end.first_name).to eq 'first_name: Jim Bob'
|
178
184
|
end
|
179
185
|
end
|
180
186
|
end
|
@@ -182,13 +188,13 @@ describe DashTest do
|
|
182
188
|
describe '#merge!' do
|
183
189
|
it 'modifies the existing instance of the Dash' do
|
184
190
|
original_dash = subject.merge!(first_name: 'Robert')
|
185
|
-
subject.object_id.
|
191
|
+
expect(subject.object_id).to eq original_dash.object_id
|
186
192
|
end
|
187
193
|
|
188
194
|
it 'merges the given hash' do
|
189
195
|
subject.merge!(first_name: 'Robert', email: 'robert@example.com')
|
190
|
-
subject.first_name.
|
191
|
-
subject.email.
|
196
|
+
expect(subject.first_name).to eq 'Robert'
|
197
|
+
expect(subject.email).to eq 'robert@example.com'
|
192
198
|
end
|
193
199
|
|
194
200
|
it 'fails with non-existent properties' do
|
@@ -201,38 +207,38 @@ describe DashTest do
|
|
201
207
|
|
202
208
|
context 'given a block' do
|
203
209
|
it "sets merged key's values to the block's return value" do
|
204
|
-
subject.merge!(first_name: 'Jim') do |key, oldval, newval|
|
210
|
+
expect(subject.merge!(first_name: 'Jim') do |key, oldval, newval|
|
205
211
|
"#{key}: #{newval} #{oldval}"
|
206
|
-
end.first_name.
|
212
|
+
end.first_name).to eq 'first_name: Jim Bob'
|
207
213
|
end
|
208
214
|
end
|
209
215
|
end
|
210
216
|
|
211
217
|
describe 'properties' do
|
212
218
|
it 'lists defined properties' do
|
213
|
-
described_class.properties.
|
219
|
+
expect(described_class.properties).to eq Set.new([:first_name, :email, :count])
|
214
220
|
end
|
215
221
|
|
216
222
|
it 'checks if a property exists' do
|
217
|
-
described_class.property?('first_name').
|
218
|
-
described_class.property?(:first_name).
|
223
|
+
expect(described_class.property?('first_name')).to be_true
|
224
|
+
expect(described_class.property?(:first_name)).to be_true
|
219
225
|
end
|
220
226
|
|
221
227
|
it 'checks if a property is required' do
|
222
|
-
described_class.required?('first_name').
|
223
|
-
described_class.required?(:first_name).
|
228
|
+
expect(described_class.required?('first_name')).to be_true
|
229
|
+
expect(described_class.required?(:first_name)).to be_true
|
224
230
|
end
|
225
231
|
|
226
232
|
it 'doesnt include property from subclass' do
|
227
|
-
described_class.property?(:last_name).
|
233
|
+
expect(described_class.property?(:last_name)).to be_false
|
228
234
|
end
|
229
235
|
|
230
236
|
it 'lists declared defaults' do
|
231
|
-
described_class.defaults.
|
237
|
+
expect(described_class.defaults).to eq(count: 0)
|
232
238
|
end
|
233
239
|
|
234
240
|
it 'allows properties that end in bang' do
|
235
|
-
PropertyBangTest.property?(:important!).
|
241
|
+
expect(PropertyBangTest.property?(:important!)).to be_true
|
236
242
|
end
|
237
243
|
end
|
238
244
|
|
@@ -240,24 +246,24 @@ describe DashTest do
|
|
240
246
|
before { subject.replace(first_name: 'Cain') }
|
241
247
|
|
242
248
|
it 'return self' do
|
243
|
-
subject.replace(email: 'bar').to_hash.
|
249
|
+
expect(subject.replace(email: 'bar').to_hash).to eq('email' => 'bar', 'count' => 0)
|
244
250
|
end
|
245
251
|
|
246
252
|
it 'sets all specified keys to their corresponding values' do
|
247
|
-
subject.first_name.
|
253
|
+
expect(subject.first_name).to eq 'Cain'
|
248
254
|
end
|
249
255
|
|
250
256
|
it 'leaves only specified keys and keys with default values' do
|
251
|
-
subject.keys.sort.
|
252
|
-
subject.email.
|
253
|
-
subject.count.
|
257
|
+
expect(subject.keys.sort).to eq %w(count first_name)
|
258
|
+
expect(subject.email).to be_nil
|
259
|
+
expect(subject.count).to eq 0
|
254
260
|
end
|
255
261
|
|
256
262
|
context 'when replacing keys with default values' do
|
257
263
|
before { subject.replace(count: 3) }
|
258
264
|
|
259
265
|
it 'sets all specified keys to their corresponding values' do
|
260
|
-
subject.count.
|
266
|
+
expect(subject.count).to eq 3
|
261
267
|
end
|
262
268
|
end
|
263
269
|
end
|
@@ -271,40 +277,40 @@ describe Hashie::Dash, 'inheritance' do
|
|
271
277
|
end
|
272
278
|
|
273
279
|
it 'reports empty properties when nothing defined' do
|
274
|
-
@top.properties.
|
275
|
-
@top.defaults.
|
280
|
+
expect(@top.properties).to be_empty
|
281
|
+
expect(@top.defaults).to be_empty
|
276
282
|
end
|
277
283
|
|
278
284
|
it 'inherits properties downwards' do
|
279
285
|
@top.property :echo
|
280
|
-
@middle.properties.
|
281
|
-
@bottom.properties.
|
286
|
+
expect(@middle.properties).to include(:echo)
|
287
|
+
expect(@bottom.properties).to include(:echo)
|
282
288
|
end
|
283
289
|
|
284
290
|
it 'doesnt inherit properties upwards' do
|
285
291
|
@middle.property :echo
|
286
|
-
@top.properties.
|
287
|
-
@bottom.properties.
|
292
|
+
expect(@top.properties).not_to include(:echo)
|
293
|
+
expect(@bottom.properties).to include(:echo)
|
288
294
|
end
|
289
295
|
|
290
296
|
it 'allows overriding a default on an existing property' do
|
291
297
|
@top.property :echo
|
292
298
|
@middle.property :echo, default: 123
|
293
|
-
@bottom.properties.to_a.
|
294
|
-
@bottom.new.echo.
|
299
|
+
expect(@bottom.properties.to_a).to eq [:echo]
|
300
|
+
expect(@bottom.new.echo).to eq 123
|
295
301
|
end
|
296
302
|
|
297
303
|
it 'allows clearing an existing default' do
|
298
304
|
@top.property :echo
|
299
305
|
@middle.property :echo, default: 123
|
300
306
|
@bottom.property :echo
|
301
|
-
@bottom.properties.to_a.
|
302
|
-
@bottom.new.echo.
|
307
|
+
expect(@bottom.properties.to_a).to eq [:echo]
|
308
|
+
expect(@bottom.new.echo).to be_nil
|
303
309
|
end
|
304
310
|
|
305
311
|
it 'allows nil defaults' do
|
306
312
|
@bottom.property :echo, default: nil
|
307
|
-
@bottom.new.
|
313
|
+
expect(@bottom.new).to have_key('echo')
|
308
314
|
end
|
309
315
|
|
310
316
|
end
|
@@ -312,7 +318,10 @@ end
|
|
312
318
|
describe Subclassed do
|
313
319
|
subject { Subclassed.new(first_name: 'Bob', last_name: 'McNob', email: 'bob@example.com') }
|
314
320
|
|
315
|
-
|
321
|
+
describe '#count' do
|
322
|
+
subject { super().count }
|
323
|
+
it { should be_zero }
|
324
|
+
end
|
316
325
|
|
317
326
|
it { should respond_to(:first_name) }
|
318
327
|
it { should respond_to(:first_name=) }
|
@@ -320,10 +329,10 @@ describe Subclassed do
|
|
320
329
|
it { should respond_to(:last_name=) }
|
321
330
|
|
322
331
|
it 'has one additional property' do
|
323
|
-
described_class.property?(:last_name).
|
332
|
+
expect(described_class.property?(:last_name)).to be_true
|
324
333
|
end
|
325
334
|
|
326
335
|
it "didn't override superclass inheritance logic" do
|
327
|
-
described_class.instance_variable_get('@inheritance_test').
|
336
|
+
expect(described_class.instance_variable_get('@inheritance_test')).to be_true
|
328
337
|
end
|
329
338
|
end
|
@@ -32,13 +32,13 @@ describe Hashie::Extensions::Coercion do
|
|
32
32
|
let(:instance) { subject.new }
|
33
33
|
|
34
34
|
describe '#coerce_key' do
|
35
|
-
it { subject.
|
35
|
+
it { expect(subject).to be_respond_to(:coerce_key) }
|
36
36
|
|
37
37
|
it 'runs through coerce on a specified key' do
|
38
38
|
subject.coerce_key :foo, Coercable
|
39
39
|
|
40
40
|
instance[:foo] = 'bar'
|
41
|
-
instance[:foo].
|
41
|
+
expect(instance[:foo]).to be_coerced
|
42
42
|
end
|
43
43
|
|
44
44
|
it 'supports an array of keys' do
|
@@ -46,23 +46,23 @@ describe Hashie::Extensions::Coercion do
|
|
46
46
|
|
47
47
|
instance[:foo] = 'bar'
|
48
48
|
instance[:bar] = 'bax'
|
49
|
-
instance[:foo].
|
50
|
-
instance[:bar].
|
49
|
+
expect(instance[:foo]).to be_coerced
|
50
|
+
expect(instance[:bar]).to be_coerced
|
51
51
|
end
|
52
52
|
|
53
53
|
it 'calls #new if no coerce method is available' do
|
54
54
|
subject.coerce_key :foo, Initializable
|
55
55
|
|
56
56
|
instance[:foo] = 'bar'
|
57
|
-
instance[:foo].value.
|
58
|
-
instance[:foo].
|
57
|
+
expect(instance[:foo].value).to eq 'String'
|
58
|
+
expect(instance[:foo]).not_to be_coerced
|
59
59
|
end
|
60
60
|
|
61
61
|
it 'coerces when the merge initializer is used' do
|
62
62
|
subject.coerce_key :foo, Coercable
|
63
63
|
instance = subject.new(foo: 'bar')
|
64
64
|
|
65
|
-
instance[:foo].
|
65
|
+
expect(instance[:foo]).to be_coerced
|
66
66
|
end
|
67
67
|
|
68
68
|
context 'when #replace is used' do
|
@@ -73,13 +73,13 @@ describe Hashie::Extensions::Coercion do
|
|
73
73
|
end
|
74
74
|
|
75
75
|
it 'coerces relevant keys' do
|
76
|
-
instance[:foo].
|
77
|
-
instance[:bar].
|
78
|
-
instance[:hi].
|
76
|
+
expect(instance[:foo]).to be_coerced
|
77
|
+
expect(instance[:bar]).to be_coerced
|
78
|
+
expect(instance[:hi]).not_to respond_to(:coerced?)
|
79
79
|
end
|
80
80
|
|
81
81
|
it 'sets correct values' do
|
82
|
-
instance[:hi].
|
82
|
+
expect(instance[:hi]).to eq 'bye'
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
@@ -93,25 +93,25 @@ describe Hashie::Extensions::Coercion do
|
|
93
93
|
|
94
94
|
it 'coerces with instance initialization' do
|
95
95
|
tweet = TweetMash.new(user: { email: 'foo@bar.com' })
|
96
|
-
tweet[:user].
|
96
|
+
expect(tweet[:user]).to be_a(UserMash)
|
97
97
|
end
|
98
98
|
|
99
99
|
it 'coerces when setting with attribute style' do
|
100
100
|
tweet = TweetMash.new
|
101
101
|
tweet.user = { email: 'foo@bar.com' }
|
102
|
-
tweet[:user].
|
102
|
+
expect(tweet[:user]).to be_a(UserMash)
|
103
103
|
end
|
104
104
|
|
105
105
|
it 'coerces when setting with string index' do
|
106
106
|
tweet = TweetMash.new
|
107
107
|
tweet['user'] = { email: 'foo@bar.com' }
|
108
|
-
tweet[:user].
|
108
|
+
expect(tweet[:user]).to be_a(UserMash)
|
109
109
|
end
|
110
110
|
|
111
111
|
it 'coerces when setting with symbol index' do
|
112
112
|
tweet = TweetMash.new
|
113
113
|
tweet[:user] = { email: 'foo@bar.com' }
|
114
|
-
tweet[:user].
|
114
|
+
expect(tweet[:user]).to be_a(UserMash)
|
115
115
|
end
|
116
116
|
end
|
117
117
|
end
|
@@ -124,9 +124,9 @@ describe Hashie::Extensions::Coercion do
|
|
124
124
|
instance[:foo] = 'bar'
|
125
125
|
instance[:bar] = 'bax'
|
126
126
|
instance[:hi] = :bye
|
127
|
-
instance[:foo].
|
128
|
-
instance[:bar].
|
129
|
-
instance[:hi].
|
127
|
+
expect(instance[:foo]).to be_coerced
|
128
|
+
expect(instance[:bar]).to be_coerced
|
129
|
+
expect(instance[:hi]).not_to respond_to(:coerced?)
|
130
130
|
end
|
131
131
|
|
132
132
|
it 'coerces values from a #replace call' do
|
@@ -134,8 +134,8 @@ describe Hashie::Extensions::Coercion do
|
|
134
134
|
|
135
135
|
instance[:foo] = :bar
|
136
136
|
instance.replace(foo: 'bar', bar: 'bax')
|
137
|
-
instance[:foo].
|
138
|
-
instance[:bar].
|
137
|
+
expect(instance[:foo]).to be_coerced
|
138
|
+
expect(instance[:bar]).to be_coerced
|
139
139
|
end
|
140
140
|
|
141
141
|
it 'does not coerce superclasses' do
|
@@ -143,9 +143,9 @@ describe Hashie::Extensions::Coercion do
|
|
143
143
|
subject.coerce_value klass, Coercable
|
144
144
|
|
145
145
|
instance[:foo] = 'bar'
|
146
|
-
instance[:foo].
|
146
|
+
expect(instance[:foo]).not_to be_kind_of(Coercable)
|
147
147
|
instance[:foo] = klass.new
|
148
|
-
instance[:foo].
|
148
|
+
expect(instance[:foo]).to be_kind_of(Coercable)
|
149
149
|
end
|
150
150
|
end
|
151
151
|
end
|
@@ -21,27 +21,27 @@ module Hashie
|
|
21
21
|
|
22
22
|
describe '#deep_fetch' do
|
23
23
|
it 'extracts a value from a nested hash' do
|
24
|
-
instance.deep_fetch(:library, :location, :address).
|
24
|
+
expect(instance.deep_fetch(:library, :location, :address)).to eq('123 Library St.')
|
25
25
|
end
|
26
26
|
|
27
27
|
it 'extracts a value from a nested array' do
|
28
|
-
instance.deep_fetch(:library, :books, 1, :title).
|
28
|
+
expect(instance.deep_fetch(:library, :books, 1, :title)).to eq('Moby Dick')
|
29
29
|
end
|
30
30
|
|
31
31
|
context 'when one of the keys is not present' do
|
32
32
|
context 'when a block is provided' do
|
33
33
|
it 'returns the value of the block' do
|
34
34
|
value = instance.deep_fetch(:library, :unknown_key, :location) { 'block value' }
|
35
|
-
value.
|
35
|
+
expect(value).to eq('block value')
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
39
|
context 'when a block is not provided' do
|
40
40
|
context 'when the nested object is an array' do
|
41
41
|
it 'raises an UndefinedPathError' do
|
42
|
-
|
42
|
+
expect do
|
43
43
|
instance.deep_fetch(:library, :books, 2)
|
44
|
-
end.
|
44
|
+
end.to(
|
45
45
|
raise_error(
|
46
46
|
DeepFetch::UndefinedPathError,
|
47
47
|
'Could not fetch path (library > books > 2) at 2'
|
@@ -52,9 +52,9 @@ module Hashie
|
|
52
52
|
|
53
53
|
context 'when the nested object is a hash' do
|
54
54
|
it 'raises a UndefinedPathError' do
|
55
|
-
|
55
|
+
expect do
|
56
56
|
instance.deep_fetch(:library, :location, :unknown_key)
|
57
|
-
end.
|
57
|
+
end.to(
|
58
58
|
raise_error(
|
59
59
|
DeepFetch::UndefinedPathError,
|
60
60
|
'Could not fetch path (library > location > unknown_key) at unknown_key'
|
@@ -12,11 +12,11 @@ describe Hashie::Extensions::DeepMerge do
|
|
12
12
|
let(:expected_hash) { { a: 1, a1: 1, b: 'b', c: { c1: 2, c2: 'c2', c3: { d1: 'd1', d2: 'd2' } } } }
|
13
13
|
|
14
14
|
it 'deep merges two hashes' do
|
15
|
-
h1.deep_merge(h2).
|
15
|
+
expect(h1.deep_merge(h2)).to eq expected_hash
|
16
16
|
end
|
17
17
|
|
18
18
|
it 'deep merges another hash in place via bang method' do
|
19
19
|
h1.deep_merge!(h2)
|
20
|
-
h1.
|
20
|
+
expect(h1).to eq expected_hash
|
21
21
|
end
|
22
22
|
end
|