hashie 3.4.3 → 5.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 +5 -5
- data/CHANGELOG.md +516 -129
- data/CONTRIBUTING.md +24 -7
- data/LICENSE +1 -1
- data/README.md +408 -50
- data/Rakefile +18 -1
- data/UPGRADING.md +157 -7
- data/hashie.gemspec +14 -8
- data/lib/hashie/array.rb +21 -0
- data/lib/hashie/clash.rb +24 -12
- data/lib/hashie/dash.rb +56 -31
- data/lib/hashie/extensions/active_support/core_ext/hash.rb +14 -0
- data/lib/hashie/extensions/array/pretty_inspect.rb +19 -0
- data/lib/hashie/extensions/coercion.rb +30 -17
- data/lib/hashie/extensions/dash/indifferent_access.rb +30 -1
- data/lib/hashie/extensions/dash/predefined_values.rb +88 -0
- data/lib/hashie/extensions/dash/property_translation.rb +59 -28
- data/lib/hashie/extensions/deep_fetch.rb +5 -3
- data/lib/hashie/extensions/deep_find.rb +14 -5
- data/lib/hashie/extensions/deep_locate.rb +40 -21
- data/lib/hashie/extensions/deep_merge.rb +26 -10
- data/lib/hashie/extensions/ignore_undeclared.rb +6 -4
- data/lib/hashie/extensions/indifferent_access.rb +49 -8
- 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 +53 -0
- data/lib/hashie/extensions/mash/permissive_respond_to.rb +61 -0
- data/lib/hashie/extensions/mash/safe_assignment.rb +3 -1
- data/lib/hashie/extensions/mash/symbolize_keys.rb +38 -0
- data/lib/hashie/extensions/method_access.rb +77 -19
- data/lib/hashie/extensions/parsers/yaml_erb_parser.rb +29 -5
- data/lib/hashie/extensions/ruby_version.rb +60 -0
- data/lib/hashie/extensions/ruby_version_check.rb +21 -0
- data/lib/hashie/extensions/strict_key_access.rb +16 -13
- data/lib/hashie/extensions/stringify_keys.rb +1 -1
- data/lib/hashie/extensions/symbolize_keys.rb +13 -2
- data/lib/hashie/hash.rb +18 -11
- data/lib/hashie/logger.rb +18 -0
- data/lib/hashie/mash.rb +177 -43
- data/lib/hashie/railtie.rb +21 -0
- data/lib/hashie/rash.rb +7 -7
- data/lib/hashie/utils.rb +44 -0
- data/lib/hashie/version.rb +1 -1
- data/lib/hashie.rb +33 -17
- metadata +28 -95
- data/spec/hashie/clash_spec.rb +0 -48
- data/spec/hashie/dash_spec.rb +0 -513
- data/spec/hashie/extensions/autoload_spec.rb +0 -24
- data/spec/hashie/extensions/coercion_spec.rb +0 -625
- 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 -45
- data/spec/hashie/extensions/deep_locate_spec.rb +0 -124
- data/spec/hashie/extensions/deep_merge_spec.rb +0 -65
- data/spec/hashie/extensions/ignore_undeclared_spec.rb +0 -46
- data/spec/hashie/extensions/indifferent_access_spec.rb +0 -219
- 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/safe_assignment_spec.rb +0 -50
- data/spec/hashie/extensions/merge_initializer_spec.rb +0 -23
- data/spec/hashie/extensions/method_access_spec.rb +0 -184
- data/spec/hashie/extensions/strict_key_access_spec.rb +0 -110
- data/spec/hashie/extensions/stringify_keys_spec.rb +0 -124
- data/spec/hashie/extensions/symbolize_keys_spec.rb +0 -129
- data/spec/hashie/hash_spec.rb +0 -84
- data/spec/hashie/mash_spec.rb +0 -680
- data/spec/hashie/parsers/yaml_erb_parser_spec.rb +0 -29
- data/spec/hashie/rash_spec.rb +0 -77
- data/spec/hashie/trash_spec.rb +0 -268
- data/spec/hashie/version_spec.rb +0 -7
- data/spec/spec_helper.rb +0 -16
- data/spec/support/module_context.rb +0 -11
data/lib/hashie/hash.rb
CHANGED
@@ -17,21 +17,22 @@ module Hashie
|
|
17
17
|
# Converts a mash back to a hash (with stringified or symbolized keys)
|
18
18
|
def to_hash(options = {})
|
19
19
|
out = {}
|
20
|
-
|
21
|
-
assignment_key =
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
20
|
+
each_key do |k|
|
21
|
+
assignment_key =
|
22
|
+
if options[:stringify_keys]
|
23
|
+
k.to_s
|
24
|
+
elsif options[:symbolize_keys] && k.respond_to?(:to_sym)
|
25
|
+
k.to_sym
|
26
|
+
else
|
27
|
+
k
|
28
|
+
end
|
28
29
|
if self[k].is_a?(Array)
|
29
30
|
out[assignment_key] ||= []
|
30
31
|
self[k].each do |array_object|
|
31
|
-
out[assignment_key] << (
|
32
|
+
out[assignment_key] << maybe_convert_to_hash(array_object, options)
|
32
33
|
end
|
33
34
|
else
|
34
|
-
out[assignment_key] = (
|
35
|
+
out[assignment_key] = maybe_convert_to_hash(self[k], options)
|
35
36
|
end
|
36
37
|
end
|
37
38
|
out
|
@@ -44,8 +45,14 @@ module Hashie
|
|
44
45
|
|
45
46
|
private
|
46
47
|
|
48
|
+
def maybe_convert_to_hash(object, options)
|
49
|
+
return object unless object.is_a?(Hash) || object.respond_to?(:to_hash)
|
50
|
+
|
51
|
+
flexibly_convert_to_hash(object, options)
|
52
|
+
end
|
53
|
+
|
47
54
|
def flexibly_convert_to_hash(object, options = {})
|
48
|
-
if object.method(:to_hash).arity
|
55
|
+
if object.method(:to_hash).arity.zero?
|
49
56
|
object.to_hash
|
50
57
|
else
|
51
58
|
object.to_hash(options)
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
module Hashie
|
4
|
+
# The logger that Hashie uses for reporting errors.
|
5
|
+
#
|
6
|
+
# @return [Logger]
|
7
|
+
def self.logger
|
8
|
+
@logger ||= Logger.new(STDOUT)
|
9
|
+
end
|
10
|
+
|
11
|
+
# Sets the logger that Hashie uses for reporting errors.
|
12
|
+
#
|
13
|
+
# @param logger [Logger] The logger to set as Hashie's logger.
|
14
|
+
# @return [void]
|
15
|
+
def self.logger=(logger)
|
16
|
+
@logger = logger
|
17
|
+
end
|
18
|
+
end
|
data/lib/hashie/mash.rb
CHANGED
@@ -1,4 +1,8 @@
|
|
1
1
|
require 'hashie/hash'
|
2
|
+
require 'hashie/array'
|
3
|
+
require 'hashie/utils'
|
4
|
+
require 'hashie/logger'
|
5
|
+
require 'hashie/extensions/key_conflict_warning'
|
2
6
|
|
3
7
|
module Hashie
|
4
8
|
# Mash allows you to create pseudo-objects that have method-like
|
@@ -12,9 +16,12 @@ module Hashie
|
|
12
16
|
#
|
13
17
|
# * No punctuation: Returns the value of the hash for that key, or nil if none exists.
|
14
18
|
# * Assignment (<tt>=</tt>): Sets the attribute of the given method name.
|
15
|
-
# *
|
16
|
-
#
|
17
|
-
# *
|
19
|
+
# * Truthiness (<tt>?</tt>): Returns true or false depending on the truthiness of
|
20
|
+
# the attribute, or false if the key is not set.
|
21
|
+
# * Bang (<tt>!</tt>): Forces the existence of this key, used for deep Mashes. Think of it
|
22
|
+
# as "touch" for mashes.
|
23
|
+
# * Under Bang (<tt>_</tt>): Like Bang, but returns a new Mash rather than creating a key.
|
24
|
+
# Used to test existance in deep Mashes.
|
18
25
|
#
|
19
26
|
# == Basic Example
|
20
27
|
#
|
@@ -55,18 +62,20 @@ module Hashie
|
|
55
62
|
# mash.author # => <Mash>
|
56
63
|
#
|
57
64
|
class Mash < Hash
|
58
|
-
include Hashie::Extensions::
|
65
|
+
include Hashie::Extensions::RubyVersionCheck
|
66
|
+
extend Hashie::Extensions::KeyConflictWarning
|
59
67
|
|
60
|
-
ALLOWED_SUFFIXES = %w
|
68
|
+
ALLOWED_SUFFIXES = %w[? ! = _].freeze
|
61
69
|
|
62
70
|
def self.load(path, options = {})
|
63
71
|
@_mashes ||= new
|
64
72
|
|
65
73
|
return @_mashes[path] if @_mashes.key?(path)
|
66
|
-
|
74
|
+
raise ArgumentError, "The following file doesn't exist: #{path}" unless File.file?(path)
|
67
75
|
|
68
|
-
|
69
|
-
|
76
|
+
options = options.dup
|
77
|
+
parser = options.delete(:parser) { Hashie::Extensions::Parsers::YamlErbParser }
|
78
|
+
@_mashes[path] = new(parser.perform(path, options)).freeze
|
70
79
|
end
|
71
80
|
|
72
81
|
def to_module(mash_method_name = :settings)
|
@@ -78,7 +87,11 @@ module Hashie
|
|
78
87
|
end
|
79
88
|
end
|
80
89
|
|
81
|
-
|
90
|
+
def with_accessors!
|
91
|
+
extend Hashie::Extensions::Mash::DefineAccessors
|
92
|
+
end
|
93
|
+
|
94
|
+
alias to_s inspect
|
82
95
|
|
83
96
|
# If you pass in an existing hash, it will
|
84
97
|
# convert it to a Mash including recursively
|
@@ -89,13 +102,26 @@ module Hashie
|
|
89
102
|
default ? super(default) : super(&blk)
|
90
103
|
end
|
91
104
|
|
92
|
-
|
105
|
+
# Creates a new anonymous subclass with key conflict
|
106
|
+
# warnings disabled. You may pass an array of method
|
107
|
+
# symbols to restrict the disabled warnings to.
|
108
|
+
# Hashie::Mash.quiet.new(hash) all warnings disabled.
|
109
|
+
# Hashie::Mash.quiet(:zip).new(hash) only zip warning
|
110
|
+
# is disabled.
|
111
|
+
def self.quiet(*method_keys)
|
112
|
+
@memoized_classes ||= {}
|
113
|
+
@memoized_classes[method_keys] ||= Class.new(self) do
|
114
|
+
disable_warnings(*method_keys)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
class << self; alias [] new; end
|
93
119
|
|
94
|
-
|
95
|
-
|
120
|
+
alias regular_reader []
|
121
|
+
alias regular_writer []=
|
96
122
|
|
97
|
-
# Retrieves an attribute set in the Mash. Will convert
|
98
|
-
#
|
123
|
+
# Retrieves an attribute set in the Mash. Will convert a key passed in
|
124
|
+
# as a symbol to a string before retrieving.
|
99
125
|
def custom_reader(key)
|
100
126
|
default_proc.call(self, key) if default_proc && !key?(key)
|
101
127
|
value = regular_reader(convert_key(key))
|
@@ -103,15 +129,16 @@ module Hashie
|
|
103
129
|
value
|
104
130
|
end
|
105
131
|
|
106
|
-
# Sets an attribute in the Mash.
|
107
|
-
#
|
108
|
-
#
|
132
|
+
# Sets an attribute in the Mash. Symbol keys will be converted to
|
133
|
+
# strings before being set, and Hashes will be converted into Mashes
|
134
|
+
# for nesting purposes.
|
109
135
|
def custom_writer(key, value, convert = true) #:nodoc:
|
136
|
+
log_built_in_message(key) if key.respond_to?(:to_sym) && log_collision?(key.to_sym)
|
110
137
|
regular_writer(convert_key(key), convert ? convert_value(value) : value)
|
111
138
|
end
|
112
139
|
|
113
|
-
|
114
|
-
|
140
|
+
alias [] custom_reader
|
141
|
+
alias []= custom_writer
|
115
142
|
|
116
143
|
# This is the bang method reader, it will return a new Mash
|
117
144
|
# if there isn't a value already assigned to the key requested.
|
@@ -144,44 +171,89 @@ module Hashie
|
|
144
171
|
super(*keys.map { |key| convert_key(key) })
|
145
172
|
end
|
146
173
|
|
147
|
-
|
174
|
+
# Returns a new instance of the class it was called on, using its keys as
|
175
|
+
# values, and its values as keys. The new values and keys will always be
|
176
|
+
# strings.
|
177
|
+
def invert
|
178
|
+
self.class.new(super)
|
179
|
+
end
|
180
|
+
|
181
|
+
# Returns a new instance of the class it was called on, containing elements
|
182
|
+
# for which the given block returns false.
|
183
|
+
def reject(&blk)
|
184
|
+
self.class.new(super(&blk))
|
185
|
+
end
|
186
|
+
|
187
|
+
# Returns a new instance of the class it was called on, containing elements
|
188
|
+
# for which the given block returns true.
|
189
|
+
def select(&blk)
|
190
|
+
self.class.new(super(&blk))
|
191
|
+
end
|
192
|
+
|
193
|
+
alias regular_dup dup
|
148
194
|
# Duplicates the current mash as a new mash.
|
149
195
|
def dup
|
150
|
-
self.class.new(self, default)
|
196
|
+
self.class.new(self, default, &default_proc)
|
151
197
|
end
|
152
198
|
|
199
|
+
alias regular_key? key?
|
153
200
|
def key?(key)
|
154
201
|
super(convert_key(key))
|
155
202
|
end
|
156
|
-
|
157
|
-
|
158
|
-
|
203
|
+
alias has_key? key?
|
204
|
+
alias include? key?
|
205
|
+
alias member? key?
|
206
|
+
|
207
|
+
if with_minimum_ruby?('2.6.0')
|
208
|
+
# Performs a deep_update on a duplicate of the
|
209
|
+
# current mash.
|
210
|
+
def deep_merge(*other_hashes, &blk)
|
211
|
+
dup.deep_update(*other_hashes, &blk)
|
212
|
+
end
|
213
|
+
|
214
|
+
# Recursively merges this mash with the passed
|
215
|
+
# in hash, merging each hash in the hierarchy.
|
216
|
+
def deep_update(*other_hashes, &blk)
|
217
|
+
other_hashes.each do |other_hash|
|
218
|
+
_deep_update(other_hash, &blk)
|
219
|
+
end
|
220
|
+
self
|
221
|
+
end
|
222
|
+
else
|
223
|
+
# Performs a deep_update on a duplicate of the
|
224
|
+
# current mash.
|
225
|
+
def deep_merge(other_hash, &blk)
|
226
|
+
dup.deep_update(other_hash, &blk)
|
227
|
+
end
|
159
228
|
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
229
|
+
# Recursively merges this mash with the passed
|
230
|
+
# in hash, merging each hash in the hierarchy.
|
231
|
+
def deep_update(other_hash, &blk)
|
232
|
+
_deep_update(other_hash, &blk)
|
233
|
+
self
|
234
|
+
end
|
164
235
|
end
|
165
|
-
alias_method :merge, :deep_merge
|
166
236
|
|
167
|
-
#
|
168
|
-
#
|
169
|
-
|
237
|
+
# Alias these lexically so they get the correctly defined
|
238
|
+
# #deep_merge and #deep_update based on ruby version.
|
239
|
+
alias merge deep_merge
|
240
|
+
alias deep_merge! deep_update
|
241
|
+
alias update deep_update
|
242
|
+
alias merge! update
|
243
|
+
|
244
|
+
def _deep_update(other_hash, &blk)
|
170
245
|
other_hash.each_pair do |k, v|
|
171
246
|
key = convert_key(k)
|
172
|
-
if
|
247
|
+
if v.is_a?(::Hash) && key?(key) && regular_reader(key).is_a?(Mash)
|
173
248
|
custom_reader(key).deep_update(v, &blk)
|
174
249
|
else
|
175
250
|
value = convert_value(v, true)
|
176
|
-
value = convert_value(
|
251
|
+
value = convert_value(yield(key, self[k], value), true) if blk && key?(k)
|
177
252
|
custom_writer(key, value, false)
|
178
253
|
end
|
179
254
|
end
|
180
|
-
self
|
181
255
|
end
|
182
|
-
|
183
|
-
alias_method :update, :deep_update
|
184
|
-
alias_method :merge!, :update
|
256
|
+
private :_deep_update
|
185
257
|
|
186
258
|
# Assigns a value to a key
|
187
259
|
def assign_property(name, value)
|
@@ -223,7 +295,7 @@ module Hashie
|
|
223
295
|
method_name.end_with?(*ALLOWED_SUFFIXES) && key?(method_name.chop)
|
224
296
|
end
|
225
297
|
|
226
|
-
def method_missing(method_name, *args, &blk)
|
298
|
+
def method_missing(method_name, *args, &blk) # rubocop:disable Style/MethodMissing
|
227
299
|
return self.[](method_name, &blk) if key?(method_name)
|
228
300
|
name, suffix = method_name_and_suffix(method_name)
|
229
301
|
case suffix
|
@@ -247,7 +319,43 @@ module Hashie
|
|
247
319
|
|
248
320
|
# another ActiveSupport method, see issue #270
|
249
321
|
def reverse_merge(other_hash)
|
250
|
-
|
322
|
+
self.class.new(other_hash).merge(self)
|
323
|
+
end
|
324
|
+
|
325
|
+
with_minimum_ruby('2.3.0') do
|
326
|
+
def dig(*keys)
|
327
|
+
super(*keys.map { |key| convert_key(key) })
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
331
|
+
with_minimum_ruby('2.4.0') do
|
332
|
+
def transform_values(&blk)
|
333
|
+
self.class.new(super(&blk))
|
334
|
+
end
|
335
|
+
|
336
|
+
# Returns a new instance of the class it was called on, with nil values
|
337
|
+
# removed.
|
338
|
+
def compact
|
339
|
+
self.class.new(super)
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
343
|
+
with_minimum_ruby('2.5.0') do
|
344
|
+
def slice(*keys)
|
345
|
+
string_keys = keys.map { |key| convert_key(key) }
|
346
|
+
self.class.new(super(*string_keys))
|
347
|
+
end
|
348
|
+
|
349
|
+
def transform_keys(&blk)
|
350
|
+
self.class.new(super(&blk))
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
|
+
with_minimum_ruby('3.0.0') do
|
355
|
+
def except(*keys)
|
356
|
+
string_keys = keys.map { |key| convert_key(key) }
|
357
|
+
self.class.new(super(*string_keys))
|
358
|
+
end
|
251
359
|
end
|
252
360
|
|
253
361
|
protected
|
@@ -267,7 +375,7 @@ module Hashie
|
|
267
375
|
end
|
268
376
|
|
269
377
|
def convert_key(key) #:nodoc:
|
270
|
-
key.to_s
|
378
|
+
key.respond_to?(:to_sym) ? key.to_s : key
|
271
379
|
end
|
272
380
|
|
273
381
|
def convert_value(val, duping = false) #:nodoc:
|
@@ -279,11 +387,37 @@ module Hashie
|
|
279
387
|
when ::Hash
|
280
388
|
val = val.dup if duping
|
281
389
|
self.class.new(val)
|
282
|
-
when Array
|
283
|
-
val.map { |e| convert_value(e) }
|
390
|
+
when ::Array
|
391
|
+
Array.new(val.map { |e| convert_value(e) })
|
284
392
|
else
|
285
393
|
val
|
286
394
|
end
|
287
395
|
end
|
396
|
+
|
397
|
+
private
|
398
|
+
|
399
|
+
def log_built_in_message(method_key)
|
400
|
+
return if self.class.disable_warnings?(method_key)
|
401
|
+
|
402
|
+
method_information = Hashie::Utils.method_information(method(method_key))
|
403
|
+
|
404
|
+
Hashie.logger.warn(
|
405
|
+
'You are setting a key that conflicts with a built-in method ' \
|
406
|
+
"#{self.class}##{method_key} #{method_information}. " \
|
407
|
+
'This can cause unexpected behavior when accessing the key as a ' \
|
408
|
+
'property. You can still access the key via the #[] method.'
|
409
|
+
)
|
410
|
+
end
|
411
|
+
|
412
|
+
def log_collision?(method_key)
|
413
|
+
return unless method_key.is_a?(String) || method_key.is_a?(Symbol)
|
414
|
+
return unless respond_to?(method_key)
|
415
|
+
|
416
|
+
_, suffix = method_name_and_suffix(method_key)
|
417
|
+
|
418
|
+
(!suffix || suffix == '='.freeze) &&
|
419
|
+
!self.class.disable_warnings?(method_key) &&
|
420
|
+
!(regular_key?(method_key) || regular_key?(method_key.to_s))
|
421
|
+
end
|
288
422
|
end
|
289
423
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
begin
|
2
|
+
require 'rails/railtie'
|
3
|
+
|
4
|
+
module Hashie
|
5
|
+
class Railtie < Rails::Railtie
|
6
|
+
# Set the Hashie.logger to use Rails.logger when used with rails.
|
7
|
+
initializer 'hashie.configure_logger', after: 'initialize_logger' do
|
8
|
+
Hashie.logger = Rails.logger
|
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
|
17
|
+
end
|
18
|
+
end
|
19
|
+
rescue LoadError => e
|
20
|
+
Hashie.logger.info("Hashie skipping railtie as #{e.message}")
|
21
|
+
end
|
data/lib/hashie/rash.rb
CHANGED
@@ -64,7 +64,7 @@ module Hashie
|
|
64
64
|
# Raise (or yield) unless something matches the key.
|
65
65
|
#
|
66
66
|
def fetch(*args)
|
67
|
-
|
67
|
+
raise ArgumentError, "Expected 1-2 arguments, got #{args.length}" \
|
68
68
|
unless (1..2).cover?(args.length)
|
69
69
|
|
70
70
|
key, default = args
|
@@ -78,7 +78,7 @@ module Hashie
|
|
78
78
|
elsif default
|
79
79
|
default
|
80
80
|
else
|
81
|
-
|
81
|
+
raise KeyError, "key not found: #{key.inspect}"
|
82
82
|
end
|
83
83
|
end
|
84
84
|
|
@@ -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
|
@@ -125,18 +125,18 @@ module Hashie
|
|
125
125
|
end
|
126
126
|
|
127
127
|
def method_missing(*args, &block)
|
128
|
-
@hash.send(*args, &block)
|
128
|
+
@hash.send(*args, &block) || super
|
129
129
|
end
|
130
130
|
|
131
|
-
def respond_to_missing?(
|
132
|
-
@hash.respond_to?(
|
131
|
+
def respond_to_missing?(method_name, _include_private = false)
|
132
|
+
@hash.respond_to?(method_name)
|
133
133
|
end
|
134
134
|
|
135
135
|
private
|
136
136
|
|
137
137
|
def optimize_if_necessary!
|
138
138
|
return unless (@lookups += 1) >= @optimize_every
|
139
|
-
@regexes = @
|
139
|
+
@regexes = @regexes.sort_by { |regex| -@regex_counts[regex] }
|
140
140
|
@lookups = 0
|
141
141
|
end
|
142
142
|
end
|
data/lib/hashie/utils.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
module Hashie
|
2
|
+
# A collection of helper methods that can be used throughout the gem.
|
3
|
+
module Utils
|
4
|
+
# Describes a method by where it was defined.
|
5
|
+
#
|
6
|
+
# @param bound_method [Method] The method to describe.
|
7
|
+
# @return [String]
|
8
|
+
def self.method_information(bound_method)
|
9
|
+
if bound_method.source_location
|
10
|
+
"defined at #{bound_method.source_location.join(':')}"
|
11
|
+
else
|
12
|
+
"defined in #{bound_method.owner}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# Duplicates a value or returns the value when it is not duplicable
|
17
|
+
#
|
18
|
+
# @api public
|
19
|
+
#
|
20
|
+
# @param value [Object] the value to safely duplicate
|
21
|
+
# @return [Object] the duplicated value
|
22
|
+
def self.safe_dup(value)
|
23
|
+
case value
|
24
|
+
when Complex, FalseClass, NilClass, Rational, Method, Symbol, TrueClass, *integer_classes
|
25
|
+
value
|
26
|
+
else
|
27
|
+
value.dup
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Lists the classes Ruby uses for integers
|
32
|
+
#
|
33
|
+
# @api private
|
34
|
+
# @return [Array<Class>]
|
35
|
+
def self.integer_classes
|
36
|
+
@integer_classes ||=
|
37
|
+
if 0.class == Integer
|
38
|
+
[Integer]
|
39
|
+
else
|
40
|
+
[Fixnum, Bignum] # rubocop:disable Lint/UnifiedInteger
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/hashie/version.rb
CHANGED
data/lib/hashie.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'hashie/logger'
|
1
2
|
require 'hashie/version'
|
2
3
|
|
3
4
|
module Hashie
|
@@ -7,26 +8,30 @@ module Hashie
|
|
7
8
|
autoload :Mash, 'hashie/mash'
|
8
9
|
autoload :Trash, 'hashie/trash'
|
9
10
|
autoload :Rash, 'hashie/rash'
|
11
|
+
autoload :Array, 'hashie/array'
|
12
|
+
autoload :Utils, 'hashie/utils'
|
10
13
|
|
11
14
|
module Extensions
|
12
|
-
autoload :Coercion,
|
13
|
-
autoload :DeepMerge,
|
14
|
-
autoload :IgnoreUndeclared,
|
15
|
-
autoload :IndifferentAccess,
|
16
|
-
autoload :MergeInitializer,
|
17
|
-
autoload :MethodAccess,
|
18
|
-
autoload :MethodQuery,
|
19
|
-
autoload :MethodReader,
|
20
|
-
autoload :MethodWriter,
|
21
|
-
autoload :StringifyKeys,
|
22
|
-
autoload :SymbolizeKeys,
|
23
|
-
autoload :DeepFetch,
|
24
|
-
autoload :DeepFind,
|
25
|
-
autoload :DeepLocate,
|
26
|
-
autoload :PrettyInspect,
|
27
|
-
autoload :KeyConversion,
|
15
|
+
autoload :Coercion, 'hashie/extensions/coercion'
|
16
|
+
autoload :DeepMerge, 'hashie/extensions/deep_merge'
|
17
|
+
autoload :IgnoreUndeclared, 'hashie/extensions/ignore_undeclared'
|
18
|
+
autoload :IndifferentAccess, 'hashie/extensions/indifferent_access'
|
19
|
+
autoload :MergeInitializer, 'hashie/extensions/merge_initializer'
|
20
|
+
autoload :MethodAccess, 'hashie/extensions/method_access'
|
21
|
+
autoload :MethodQuery, 'hashie/extensions/method_access'
|
22
|
+
autoload :MethodReader, 'hashie/extensions/method_access'
|
23
|
+
autoload :MethodWriter, 'hashie/extensions/method_access'
|
24
|
+
autoload :StringifyKeys, 'hashie/extensions/stringify_keys'
|
25
|
+
autoload :SymbolizeKeys, 'hashie/extensions/symbolize_keys'
|
26
|
+
autoload :DeepFetch, 'hashie/extensions/deep_fetch'
|
27
|
+
autoload :DeepFind, 'hashie/extensions/deep_find'
|
28
|
+
autoload :DeepLocate, 'hashie/extensions/deep_locate'
|
29
|
+
autoload :PrettyInspect, 'hashie/extensions/pretty_inspect'
|
30
|
+
autoload :KeyConversion, 'hashie/extensions/key_conversion'
|
28
31
|
autoload :MethodAccessWithOverride, 'hashie/extensions/method_access'
|
29
|
-
autoload :StrictKeyAccess,
|
32
|
+
autoload :StrictKeyAccess, 'hashie/extensions/strict_key_access'
|
33
|
+
autoload :RubyVersion, 'hashie/extensions/ruby_version'
|
34
|
+
autoload :RubyVersionCheck, 'hashie/extensions/ruby_version_check'
|
30
35
|
|
31
36
|
module Parsers
|
32
37
|
autoload :YamlErbParser, 'hashie/extensions/parsers/yaml_erb_parser'
|
@@ -36,10 +41,19 @@ module Hashie
|
|
36
41
|
autoload :IndifferentAccess, 'hashie/extensions/dash/indifferent_access'
|
37
42
|
autoload :PropertyTranslation, 'hashie/extensions/dash/property_translation'
|
38
43
|
autoload :Coercion, 'hashie/extensions/dash/coercion'
|
44
|
+
autoload :PredefinedValues, 'hashie/extensions/dash/predefined_values'
|
39
45
|
end
|
40
46
|
|
41
47
|
module Mash
|
48
|
+
autoload :KeepOriginalKeys, 'hashie/extensions/mash/keep_original_keys'
|
49
|
+
autoload :PermissiveRespondTo, 'hashie/extensions/mash/permissive_respond_to'
|
42
50
|
autoload :SafeAssignment, 'hashie/extensions/mash/safe_assignment'
|
51
|
+
autoload :SymbolizeKeys, 'hashie/extensions/mash/symbolize_keys'
|
52
|
+
autoload :DefineAccessors, 'hashie/extensions/mash/define_accessors'
|
53
|
+
end
|
54
|
+
|
55
|
+
module Array
|
56
|
+
autoload :PrettyInspect, 'hashie/extensions/array/pretty_inspect'
|
43
57
|
end
|
44
58
|
end
|
45
59
|
|
@@ -47,4 +61,6 @@ module Hashie
|
|
47
61
|
include Hashie::Extensions::StringifyKeys::ClassMethods
|
48
62
|
include Hashie::Extensions::SymbolizeKeys::ClassMethods
|
49
63
|
end
|
64
|
+
|
65
|
+
require 'hashie/railtie' if defined?(::Rails)
|
50
66
|
end
|