hashie 3.6.0 → 4.0.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 +28 -0
- data/README.md +95 -7
- data/UPGRADING.md +78 -2
- data/hashie.gemspec +2 -1
- data/lib/hashie.rb +20 -19
- data/lib/hashie/dash.rb +2 -1
- data/lib/hashie/extensions/active_support/core_ext/hash.rb +14 -0
- data/lib/hashie/extensions/coercion.rb +23 -16
- data/lib/hashie/extensions/dash/indifferent_access.rb +20 -1
- data/lib/hashie/extensions/dash/property_translation.rb +5 -2
- data/lib/hashie/extensions/deep_fetch.rb +4 -2
- data/lib/hashie/extensions/deep_find.rb +12 -3
- data/lib/hashie/extensions/deep_locate.rb +22 -7
- data/lib/hashie/extensions/indifferent_access.rb +1 -3
- data/lib/hashie/extensions/key_conflict_warning.rb +55 -0
- data/lib/hashie/extensions/mash/define_accessors.rb +90 -0
- data/lib/hashie/extensions/mash/keep_original_keys.rb +2 -1
- data/lib/hashie/extensions/mash/safe_assignment.rb +3 -1
- data/lib/hashie/extensions/method_access.rb +5 -2
- data/lib/hashie/extensions/parsers/yaml_erb_parser.rb +9 -4
- data/lib/hashie/extensions/strict_key_access.rb +8 -4
- data/lib/hashie/hash.rb +16 -9
- data/lib/hashie/mash.rb +99 -43
- data/lib/hashie/railtie.rb +7 -0
- data/lib/hashie/rash.rb +1 -1
- data/lib/hashie/version.rb +1 -1
- data/spec/hashie/dash_spec.rb +18 -8
- data/spec/hashie/extensions/coercion_spec.rb +17 -8
- data/spec/hashie/extensions/deep_find_spec.rb +12 -6
- data/spec/hashie/extensions/deep_locate_spec.rb +2 -1
- data/spec/hashie/extensions/deep_merge_spec.rb +6 -2
- data/spec/hashie/extensions/ignore_undeclared_spec.rb +2 -1
- data/spec/hashie/extensions/mash/define_accessors_spec.rb +90 -0
- data/spec/hashie/extensions/method_access_spec.rb +8 -1
- data/spec/hashie/extensions/strict_key_access_spec.rb +9 -10
- data/spec/hashie/extensions/symbolize_keys_spec.rb +3 -1
- data/spec/hashie/hash_spec.rb +45 -6
- data/spec/hashie/mash_spec.rb +314 -8
- data/spec/hashie/trash_spec.rb +9 -3
- data/spec/integration/elasticsearch/integration_spec.rb +3 -2
- data/spec/integration/rails/app.rb +5 -12
- data/spec/integration/rails/integration_spec.rb +22 -1
- metadata +8 -4
data/lib/hashie/mash.rb
CHANGED
@@ -2,6 +2,7 @@ require 'hashie/hash'
|
|
2
2
|
require 'hashie/array'
|
3
3
|
require 'hashie/utils'
|
4
4
|
require 'hashie/logger'
|
5
|
+
require 'hashie/extensions/key_conflict_warning'
|
5
6
|
|
6
7
|
module Hashie
|
7
8
|
# Mash allows you to create pseudo-objects that have method-like
|
@@ -16,8 +17,10 @@ module Hashie
|
|
16
17
|
# * No punctuation: Returns the value of the hash for that key, or nil if none exists.
|
17
18
|
# * Assignment (<tt>=</tt>): Sets the attribute of the given method name.
|
18
19
|
# * Existence (<tt>?</tt>): Returns true or false depending on whether that key has been set.
|
19
|
-
# * Bang (<tt>!</tt>): Forces the existence of this key, used for deep Mashes. Think of it
|
20
|
-
#
|
20
|
+
# * Bang (<tt>!</tt>): Forces the existence of this key, used for deep Mashes. Think of it
|
21
|
+
# as "touch" for mashes.
|
22
|
+
# * Under Bang (<tt>_</tt>): Like Bang, but returns a new Mash rather than creating a key.
|
23
|
+
# Used to test existance in deep Mashes.
|
21
24
|
#
|
22
25
|
# == Basic Example
|
23
26
|
#
|
@@ -60,41 +63,10 @@ module Hashie
|
|
60
63
|
class Mash < Hash
|
61
64
|
include Hashie::Extensions::PrettyInspect
|
62
65
|
include Hashie::Extensions::RubyVersionCheck
|
66
|
+
extend Hashie::Extensions::KeyConflictWarning
|
63
67
|
|
64
68
|
ALLOWED_SUFFIXES = %w[? ! = _].freeze
|
65
69
|
|
66
|
-
class CannotDisableMashWarnings < StandardError
|
67
|
-
def initialize(message = 'You cannot disable warnings on the base Mash class. Please subclass the Mash and disable it in the subclass.')
|
68
|
-
super(message)
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
# Disable the logging of warnings based on keys conflicting keys/methods
|
73
|
-
#
|
74
|
-
# @api semipublic
|
75
|
-
# @return [void]
|
76
|
-
def self.disable_warnings
|
77
|
-
raise CannotDisableMashWarnings if self == Hashie::Mash
|
78
|
-
@disable_warnings = true
|
79
|
-
end
|
80
|
-
|
81
|
-
# Checks whether this class disables warnings for conflicting keys/methods
|
82
|
-
#
|
83
|
-
# @api semipublic
|
84
|
-
# @return [Boolean]
|
85
|
-
def self.disable_warnings?
|
86
|
-
@disable_warnings ||= false
|
87
|
-
end
|
88
|
-
|
89
|
-
# Inheritance hook that sets class configuration when inherited.
|
90
|
-
#
|
91
|
-
# @api semipublic
|
92
|
-
# @return [void]
|
93
|
-
def self.inherited(subclass)
|
94
|
-
super
|
95
|
-
subclass.disable_warnings if disable_warnings?
|
96
|
-
end
|
97
|
-
|
98
70
|
def self.load(path, options = {})
|
99
71
|
@_mashes ||= new
|
100
72
|
|
@@ -102,7 +74,7 @@ module Hashie
|
|
102
74
|
raise ArgumentError, "The following file doesn't exist: #{path}" unless File.file?(path)
|
103
75
|
|
104
76
|
parser = options.fetch(:parser) { Hashie::Extensions::Parsers::YamlErbParser }
|
105
|
-
@_mashes[path] = new(parser.perform(path)).freeze
|
77
|
+
@_mashes[path] = new(parser.perform(path, options.except(:parser))).freeze
|
106
78
|
end
|
107
79
|
|
108
80
|
def to_module(mash_method_name = :settings)
|
@@ -114,6 +86,10 @@ module Hashie
|
|
114
86
|
end
|
115
87
|
end
|
116
88
|
|
89
|
+
def with_accessors!
|
90
|
+
extend Hashie::Extensions::Mash::DefineAccessors
|
91
|
+
end
|
92
|
+
|
117
93
|
alias to_s inspect
|
118
94
|
|
119
95
|
# If you pass in an existing hash, it will
|
@@ -125,6 +101,19 @@ module Hashie
|
|
125
101
|
default ? super(default) : super(&blk)
|
126
102
|
end
|
127
103
|
|
104
|
+
# Creates a new anonymous subclass with key conflict
|
105
|
+
# warnings disabled. You may pass an array of method
|
106
|
+
# symbols to restrict the disabled warnings to.
|
107
|
+
# Hashie::Mash.quiet.new(hash) all warnings disabled.
|
108
|
+
# Hashie::Mash.quiet(:zip).new(hash) only zip warning
|
109
|
+
# is disabled.
|
110
|
+
def self.quiet(*method_keys)
|
111
|
+
@memoized_classes ||= {}
|
112
|
+
@memoized_classes[method_keys] ||= Class.new(self) do
|
113
|
+
disable_warnings(*method_keys)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
128
117
|
class << self; alias [] new; end
|
129
118
|
|
130
119
|
alias regular_reader []
|
@@ -183,6 +172,31 @@ module Hashie
|
|
183
172
|
super(*keys.map { |key| convert_key(key) })
|
184
173
|
end
|
185
174
|
|
175
|
+
# Returns a new instance of the class it was called on, with nil values
|
176
|
+
# removed.
|
177
|
+
def compact
|
178
|
+
self.class.new(super)
|
179
|
+
end
|
180
|
+
|
181
|
+
# Returns a new instance of the class it was called on, using its keys as
|
182
|
+
# values, and its values as keys. The new values and keys will always be
|
183
|
+
# strings.
|
184
|
+
def invert
|
185
|
+
self.class.new(super)
|
186
|
+
end
|
187
|
+
|
188
|
+
# Returns a new instance of the class it was called on, containing elements
|
189
|
+
# for which the given block returns false.
|
190
|
+
def reject(&blk)
|
191
|
+
self.class.new(super(&blk))
|
192
|
+
end
|
193
|
+
|
194
|
+
# Returns a new instance of the class it was called on, containing elements
|
195
|
+
# for which the given block returns true.
|
196
|
+
def select(&blk)
|
197
|
+
self.class.new(super(&blk))
|
198
|
+
end
|
199
|
+
|
186
200
|
alias regular_dup dup
|
187
201
|
# Duplicates the current mash as a new mash.
|
188
202
|
def dup
|
@@ -202,14 +216,42 @@ module Hashie
|
|
202
216
|
def deep_merge(other_hash, &blk)
|
203
217
|
dup.deep_update(other_hash, &blk)
|
204
218
|
end
|
205
|
-
alias merge deep_merge
|
206
219
|
|
207
220
|
# Recursively merges this mash with the passed
|
208
221
|
# in hash, merging each hash in the hierarchy.
|
209
222
|
def deep_update(other_hash, &blk)
|
223
|
+
_deep_update(other_hash, &blk)
|
224
|
+
self
|
225
|
+
end
|
226
|
+
|
227
|
+
with_minimum_ruby('2.6.0') do
|
228
|
+
# Performs a deep_update on a duplicate of the
|
229
|
+
# current mash.
|
230
|
+
def deep_merge(*other_hashes, &blk)
|
231
|
+
dup.deep_update(*other_hashes, &blk)
|
232
|
+
end
|
233
|
+
|
234
|
+
# Recursively merges this mash with the passed
|
235
|
+
# in hash, merging each hash in the hierarchy.
|
236
|
+
def deep_update(*other_hashes, &blk)
|
237
|
+
other_hashes.each do |other_hash|
|
238
|
+
_deep_update(other_hash, &blk)
|
239
|
+
end
|
240
|
+
self
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
# Alias these lexically so they get the correctly defined
|
245
|
+
# #deep_merge and #deep_update based on ruby version.
|
246
|
+
alias merge deep_merge
|
247
|
+
alias deep_merge! deep_update
|
248
|
+
alias update deep_update
|
249
|
+
alias merge! update
|
250
|
+
|
251
|
+
def _deep_update(other_hash, &blk)
|
210
252
|
other_hash.each_pair do |k, v|
|
211
253
|
key = convert_key(k)
|
212
|
-
if
|
254
|
+
if v.is_a?(::Hash) && key?(key) && regular_reader(key).is_a?(Mash)
|
213
255
|
custom_reader(key).deep_update(v, &blk)
|
214
256
|
else
|
215
257
|
value = convert_value(v, true)
|
@@ -217,11 +259,8 @@ module Hashie
|
|
217
259
|
custom_writer(key, value, false)
|
218
260
|
end
|
219
261
|
end
|
220
|
-
self
|
221
262
|
end
|
222
|
-
|
223
|
-
alias update deep_update
|
224
|
-
alias merge! update
|
263
|
+
private :_deep_update
|
225
264
|
|
226
265
|
# Assigns a value to a key
|
227
266
|
def assign_property(name, value)
|
@@ -296,6 +335,23 @@ module Hashie
|
|
296
335
|
end
|
297
336
|
end
|
298
337
|
|
338
|
+
with_minimum_ruby('2.4.0') do
|
339
|
+
def transform_values(&blk)
|
340
|
+
self.class.new(super(&blk))
|
341
|
+
end
|
342
|
+
end
|
343
|
+
|
344
|
+
with_minimum_ruby('2.5.0') do
|
345
|
+
def slice(*keys)
|
346
|
+
string_keys = keys.map { |key| convert_key(key) }
|
347
|
+
self.class.new(super(*string_keys))
|
348
|
+
end
|
349
|
+
|
350
|
+
def transform_keys(&blk)
|
351
|
+
self.class.new(super(&blk))
|
352
|
+
end
|
353
|
+
end
|
354
|
+
|
299
355
|
protected
|
300
356
|
|
301
357
|
def method_name_and_suffix(method_name)
|
@@ -337,7 +393,7 @@ module Hashie
|
|
337
393
|
private
|
338
394
|
|
339
395
|
def log_built_in_message(method_key)
|
340
|
-
return if self.class.disable_warnings?
|
396
|
+
return if self.class.disable_warnings?(method_key)
|
341
397
|
|
342
398
|
method_information = Hashie::Utils.method_information(method(method_key))
|
343
399
|
|
@@ -350,7 +406,7 @@ module Hashie
|
|
350
406
|
end
|
351
407
|
|
352
408
|
def log_collision?(method_key)
|
353
|
-
respond_to?(method_key) && !self.class.disable_warnings? &&
|
409
|
+
respond_to?(method_key) && !self.class.disable_warnings?(method_key) &&
|
354
410
|
!(regular_key?(method_key) || regular_key?(method_key.to_s))
|
355
411
|
end
|
356
412
|
end
|
data/lib/hashie/railtie.rb
CHANGED
@@ -7,6 +7,13 @@ begin
|
|
7
7
|
initializer 'hashie.configure_logger', after: 'initialize_logger' do
|
8
8
|
Hashie.logger = Rails.logger
|
9
9
|
end
|
10
|
+
|
11
|
+
initializer 'hashie.patch_hash_except', after: 'load_active_support' do
|
12
|
+
if Rails::VERSION::MAJOR >= 6
|
13
|
+
require 'hashie/extensions/active_support/core_ext/hash'
|
14
|
+
Hashie::Mash.send(:include, Hashie::Extensions::ActiveSupport::CoreExt::Hash)
|
15
|
+
end
|
16
|
+
end
|
10
17
|
end
|
11
18
|
end
|
12
19
|
rescue LoadError => e
|
data/lib/hashie/rash.rb
CHANGED
@@ -117,7 +117,7 @@ module Hashie
|
|
117
117
|
end
|
118
118
|
|
119
119
|
when Regexp
|
120
|
-
# Reverse operation: `rash[/regexp/]` returns all
|
120
|
+
# Reverse operation: `rash[/regexp/]` returns all string keys matching the regexp
|
121
121
|
@hash.each do |key, val|
|
122
122
|
yield val if key.is_a?(String) && query =~ key
|
123
123
|
end
|
data/lib/hashie/version.rb
CHANGED
data/spec/hashie/dash_spec.rb
CHANGED
@@ -129,12 +129,14 @@ describe DashTest do
|
|
129
129
|
context 'writing to properties' do
|
130
130
|
it 'fails writing a required property to nil' do
|
131
131
|
expect { subject.first_name = nil }.to raise_error(*property_required_error('first_name'))
|
132
|
-
expect { required_message.first_name = nil }
|
132
|
+
expect { required_message.first_name = nil }
|
133
|
+
.to raise_error(*property_required_custom_error('first_name'))
|
133
134
|
end
|
134
135
|
|
135
136
|
it 'fails writing a required property to nil using []=' do
|
136
137
|
expect { subject[:first_name] = nil }.to raise_error(*property_required_error('first_name'))
|
137
|
-
expect { required_message[:first_name] = nil }
|
138
|
+
expect { required_message[:first_name] = nil }
|
139
|
+
.to raise_error(*property_required_custom_error('first_name'))
|
138
140
|
end
|
139
141
|
|
140
142
|
it 'fails writing to a non-existent property using []=' do
|
@@ -263,11 +265,13 @@ describe DashTest do
|
|
263
265
|
end
|
264
266
|
|
265
267
|
it 'fails with non-existent properties' do
|
266
|
-
expect { subject.merge(middle_name: 'James') }
|
268
|
+
expect { subject.merge(middle_name: 'James') }
|
269
|
+
.to raise_error(*no_property_error('middle_name'))
|
267
270
|
end
|
268
271
|
|
269
272
|
it 'errors out when attempting to set a required property to nil' do
|
270
|
-
expect { subject.merge(first_name: nil) }
|
273
|
+
expect { subject.merge(first_name: nil) }
|
274
|
+
.to raise_error(*property_required_error('first_name'))
|
271
275
|
end
|
272
276
|
|
273
277
|
context 'given a block' do
|
@@ -366,8 +370,12 @@ describe DashTest do
|
|
366
370
|
let(:params) { { first_name: 'Alice', email: 'alice@example.com' } }
|
367
371
|
|
368
372
|
context 'when there is coercion' do
|
369
|
-
let(:params_before)
|
370
|
-
|
373
|
+
let(:params_before) do
|
374
|
+
{ city: 'nyc', person: { first_name: 'Bob', email: 'bob@example.com' } }
|
375
|
+
end
|
376
|
+
let(:params_after) do
|
377
|
+
{ city: 'sfo', person: { first_name: 'Alice', email: 'alice@example.com' } }
|
378
|
+
end
|
371
379
|
|
372
380
|
subject { DashWithCoercion.new(params_before) }
|
373
381
|
|
@@ -505,7 +513,8 @@ end
|
|
505
513
|
|
506
514
|
describe ConditionallyRequiredTest do
|
507
515
|
it 'does not allow a conditionally required property to be set to nil if required' do
|
508
|
-
expect { ConditionallyRequiredTest.new(username: 'bob.smith', password: nil) }
|
516
|
+
expect { ConditionallyRequiredTest.new(username: 'bob.smith', password: nil) }
|
517
|
+
.to raise_error(ArgumentError, "The property 'password' must be set, too.")
|
509
518
|
end
|
510
519
|
|
511
520
|
it 'allows a conditionally required property to be set to nil if not required' do
|
@@ -513,7 +522,8 @@ describe ConditionallyRequiredTest do
|
|
513
522
|
end
|
514
523
|
|
515
524
|
it 'allows a conditionally required property to be set if required' do
|
516
|
-
expect { ConditionallyRequiredTest.new(username: 'bob.smith', password: '$ecure!') }
|
525
|
+
expect { ConditionallyRequiredTest.new(username: 'bob.smith', password: '$ecure!') }
|
526
|
+
.not_to raise_error
|
517
527
|
end
|
518
528
|
end
|
519
529
|
|
@@ -283,7 +283,8 @@ describe Hashie::Extensions::Coercion do
|
|
283
283
|
|
284
284
|
it 'raises errors for non-coercable types' do
|
285
285
|
subject.coerce_key :foo, NotInitializable
|
286
|
-
expect { instance[:foo] = 'true' }
|
286
|
+
expect { instance[:foo] = 'true' }
|
287
|
+
.to raise_error(Hashie::CoercionError, /NotInitializable is not a coercable type/)
|
287
288
|
end
|
288
289
|
|
289
290
|
it 'can coerce false' do
|
@@ -458,8 +459,12 @@ describe Hashie::Extensions::Coercion do
|
|
458
459
|
coerce_key :categories, Array[CategoryHash]
|
459
460
|
end
|
460
461
|
|
461
|
-
let(:category)
|
462
|
-
|
462
|
+
let(:category) do
|
463
|
+
CategoryHash.new(type: 'rubygem', products: [Hashie::Mash.new(name: 'Hashie')])
|
464
|
+
end
|
465
|
+
let(:product) do
|
466
|
+
ProductHash.new(name: 'Hashie', categories: [Hashie::Mash.new(type: 'rubygem')])
|
467
|
+
end
|
463
468
|
|
464
469
|
it 'coerces CategoryHash[:products] correctly' do
|
465
470
|
expected = [ProductHash]
|
@@ -559,22 +564,26 @@ describe Hashie::Extensions::Coercion do
|
|
559
564
|
|
560
565
|
it 'raises a CoercionError when coercion is not possible' do
|
561
566
|
type =
|
562
|
-
if Hashie::Extensions::RubyVersion.new(RUBY_VERSION) >=
|
567
|
+
if Hashie::Extensions::RubyVersion.new(RUBY_VERSION) >=
|
568
|
+
Hashie::Extensions::RubyVersion.new('2.4.0')
|
563
569
|
Integer
|
564
570
|
else
|
565
|
-
Fixnum
|
571
|
+
Fixnum
|
566
572
|
end
|
567
573
|
|
568
574
|
subject.coerce_value type, Symbol
|
569
|
-
expect { instance[:hi] = 1 }.to raise_error(
|
575
|
+
expect { instance[:hi] = 1 }.to raise_error(
|
576
|
+
Hashie::CoercionError, /Cannot coerce property :hi from #{type} to Symbol/
|
577
|
+
)
|
570
578
|
end
|
571
579
|
|
572
580
|
it 'coerces Integer to String' do
|
573
581
|
type =
|
574
|
-
if Hashie::Extensions::RubyVersion.new(RUBY_VERSION) >=
|
582
|
+
if Hashie::Extensions::RubyVersion.new(RUBY_VERSION) >=
|
583
|
+
Hashie::Extensions::RubyVersion.new('2.4.0')
|
575
584
|
Integer
|
576
585
|
else
|
577
|
-
Fixnum
|
586
|
+
Fixnum
|
578
587
|
end
|
579
588
|
|
580
589
|
subject.coerce_value type, String
|
@@ -36,7 +36,8 @@ describe Hashie::Extensions::DeepFind do
|
|
36
36
|
|
37
37
|
describe '#deep_find_all' do
|
38
38
|
it 'detects all values from a nested hash' do
|
39
|
-
expect(instance.deep_find_all(:title))
|
39
|
+
expect(instance.deep_find_all(:title))
|
40
|
+
.to eq(['Call of the Wild', 'Moby Dick', 'Main Library'])
|
40
41
|
end
|
41
42
|
|
42
43
|
it 'returns nil if it does not find any matches' do
|
@@ -64,7 +65,8 @@ describe Hashie::Extensions::DeepFind do
|
|
64
65
|
end
|
65
66
|
|
66
67
|
it 'detects all values from a nested hash' do
|
67
|
-
expect(instance.deep_find_all(:title))
|
68
|
+
expect(instance.deep_find_all(:title))
|
69
|
+
.to eq([{ type: :string }, 'Call of the Wild', 'Moby Dick', 'Main Library'])
|
68
70
|
end
|
69
71
|
end
|
70
72
|
end
|
@@ -91,8 +93,10 @@ describe Hashie::Extensions::DeepFind do
|
|
91
93
|
|
92
94
|
describe '#deep_find_all' do
|
93
95
|
it 'indifferently detects all values from a nested hash' do
|
94
|
-
expect(instance.deep_find_all(:title))
|
95
|
-
|
96
|
+
expect(instance.deep_find_all(:title))
|
97
|
+
.to eq(['Call of the Wild', 'Moby Dick', 'Main Library'])
|
98
|
+
expect(instance.deep_find_all('title'))
|
99
|
+
.to eq(['Call of the Wild', 'Moby Dick', 'Main Library'])
|
96
100
|
end
|
97
101
|
|
98
102
|
it 'indifferently returns nil if it does not find any matches' do
|
@@ -125,8 +129,10 @@ describe Hashie::Extensions::DeepFind do
|
|
125
129
|
|
126
130
|
describe '#deep_find_all' do
|
127
131
|
it 'indifferently detects all values from a nested hash' do
|
128
|
-
expect(instance.deep_find_all(:title))
|
129
|
-
|
132
|
+
expect(instance.deep_find_all(:title))
|
133
|
+
.to eq(['Call of the Wild', 'Moby Dick', 'Main Library'])
|
134
|
+
expect(instance.deep_find_all('title'))
|
135
|
+
.to eq(['Call of the Wild', 'Moby Dick', 'Main Library'])
|
130
136
|
end
|
131
137
|
|
132
138
|
it 'indifferently returns nil if it does not find any matches' do
|
@@ -56,7 +56,8 @@ describe Hashie::Extensions::DeepLocate do
|
|
56
56
|
describe '.deep_locate' do
|
57
57
|
context 'if called with a non-callable comparator' do
|
58
58
|
it 'creates a key comparator on-th-fly' do
|
59
|
-
expect(described_class.deep_locate(:lsr10, hash))
|
59
|
+
expect(described_class.deep_locate(:lsr10, hash))
|
60
|
+
.to eq([hash[:query][:bool][:must_not][0][:range]])
|
60
61
|
end
|
61
62
|
end
|
62
63
|
|
@@ -13,9 +13,13 @@ describe Hashie::Extensions::DeepMerge do
|
|
13
13
|
end
|
14
14
|
|
15
15
|
context 'without &block' do
|
16
|
-
let(:h1)
|
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
|
17
19
|
let(:h2) { { a: 1, a1: 1, c: { c1: 2, c2: 'c2', c3: { d2: 'd2' } }, e: { e1: 1 } } }
|
18
|
-
let(:expected_hash)
|
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
|
19
23
|
|
20
24
|
it 'deep merges two hashes' do
|
21
25
|
expect(h1.deep_merge(h2)).to eq expected_hash
|