hanami-utils 1.3.7 → 2.0.0.alpha1

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.
@@ -1,28 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "hanami/utils/duplicable"
4
3
  require "transproc"
5
4
 
6
5
  module Hanami
7
6
  module Utils
8
- # Hash on steroids
7
+ # Hash transformations
9
8
  # @since 0.1.0
10
- #
11
- class Hash
12
- # @since 0.6.0
13
- # @api private
14
- #
15
- # @see Hanami::Utils::Hash#deep_dup
16
- # @see Hanami::Utils::Duplicable
17
- DUPLICATE_LOGIC = proc do |value|
18
- case value
19
- when Hash
20
- value.deep_dup
21
- when ::Hash
22
- Hash.new(value).deep_dup.to_h
23
- end
24
- end.freeze
25
-
9
+ module Hash
26
10
  extend Transproc::Registry
27
11
  import Transproc::HashTransformations
28
12
 
@@ -48,7 +32,7 @@ module Hanami
48
32
  self[:symbolize_keys].call(input)
49
33
  end
50
34
 
51
- # Performs deep symbolize on the given hash
35
+ # Deep symbolize the given hash
52
36
  #
53
37
  # @param input [::Hash] the input
54
38
  #
@@ -70,7 +54,7 @@ module Hanami
70
54
  self[:deep_symbolize_keys].call(input)
71
55
  end
72
56
 
73
- # Stringifies the given hash
57
+ # Stringify the given hash
74
58
  #
75
59
  # @param input [::Hash] the input
76
60
  #
@@ -90,7 +74,7 @@ module Hanami
90
74
  self[:stringify_keys].call(input)
91
75
  end
92
76
 
93
- # Deeply stringifies the given hash
77
+ # Deeply stringify the given hash
94
78
  #
95
79
  # @param input [::Hash] the input
96
80
  #
@@ -106,7 +90,7 @@ module Hanami
106
90
  #
107
91
  # hash.class
108
92
  # # => Hash
109
- def self.deep_stringify(input)
93
+ def self.deep_stringify(input) # rubocop:disable Metrics/MethodLength
110
94
  input.each_with_object({}) do |(key, value), output|
111
95
  output[key.to_s] =
112
96
  case value
@@ -122,15 +106,15 @@ module Hanami
122
106
  end
123
107
  end
124
108
 
125
- # Deep duplicates hash values
109
+ # Deep duplicate hash values
126
110
  #
127
- # The output of this function is a deep duplicate of the input.
111
+ # The output of this function is a shallow duplicate of the input.
128
112
  # Any further modification on the input, won't be reflected on the output
129
113
  # and viceversa.
130
114
  #
131
115
  # @param input [::Hash] the input
132
116
  #
133
- # @return [::Hash] the deep duplicate of input
117
+ # @return [::Hash] the shallow duplicate of input
134
118
  #
135
119
  # @since 1.0.1
136
120
  #
@@ -165,12 +149,12 @@ module Hanami
165
149
  when ::Hash
166
150
  deep_dup(v)
167
151
  else
168
- Duplicable.dup(v)
152
+ v.dup
169
153
  end
170
154
  end
171
155
  end
172
156
 
173
- # Deep serializes given object into a `Hash`
157
+ # Deep serialize given object into a `Hash`
174
158
  #
175
159
  # Please note that the returning `Hash` will use symbols as keys.
176
160
  #
@@ -194,7 +178,7 @@ module Hanami
194
178
  #
195
179
  # Hanami::Utils::Hash.deep_serialize(input)
196
180
  # # => {:foo=>"bar", :baz=>[{:hello=>"world"}]}
197
- def self.deep_serialize(input)
181
+ def self.deep_serialize(input) # rubocop:disable Metrics/MethodLength
198
182
  input.to_hash.each_with_object({}) do |(key, value), output|
199
183
  output[key.to_sym] =
200
184
  case value
@@ -209,319 +193,6 @@ module Hanami
209
193
  end
210
194
  end
211
195
  end
212
-
213
- # Initialize the hash
214
- #
215
- # @param hash [#to_h] the value we want to use to initialize this instance
216
- # @param blk [Proc] define the default value
217
- #
218
- # @return [Hanami::Utils::Hash] self
219
- #
220
- # @since 0.1.0
221
- # @deprecated
222
- #
223
- # @see http://www.ruby-doc.org/core/Hash.html#method-c-5B-5D
224
- #
225
- # @example Passing a Hash
226
- # require 'hanami/utils/hash'
227
- #
228
- # hash = Hanami::Utils::Hash.new('l' => 23)
229
- # hash['l'] # => 23
230
- #
231
- # @example Passing a block for default
232
- # require 'hanami/utils/hash'
233
- #
234
- # hash = Hanami::Utils::Hash.new {|h,k| h[k] = [] }
235
- # hash['foo'].push 'bar'
236
- #
237
- # hash.to_h # => { 'foo' => ['bar'] }
238
- def initialize(hash = {}, &blk)
239
- @hash = hash.to_hash
240
- @hash.default_proc = blk if blk
241
- end
242
-
243
- # Converts in-place all the keys to Symbol instances.
244
- #
245
- # @return [Hash] self
246
- #
247
- # @since 0.1.0
248
- # @deprecated Use {Hanami::Utils::Hash.symbolize}
249
- #
250
- # @example
251
- # require 'hanami/utils/hash'
252
- #
253
- # hash = Hanami::Utils::Hash.new 'a' => 23, 'b' => { 'c' => ['x','y','z'] }
254
- # hash.symbolize!
255
- #
256
- # hash.keys # => [:a, :b]
257
- # hash.inspect # => { :a => 23, :b => { 'c' => ["x", "y", "z"] } }
258
- def symbolize!
259
- keys.each do |k|
260
- v = delete(k)
261
- self[k.to_sym] = v
262
- end
263
-
264
- self
265
- end
266
-
267
- # Converts in-place all the keys to Symbol instances, nested hashes are converted too.
268
- #
269
- # @return [Hash] self
270
- #
271
- # @since 1.0.0
272
- # @deprecated Use {Hanami::Utils::Hash.deep_symbolize}
273
- #
274
- # @example
275
- # require 'hanami/utils/hash'
276
- #
277
- # hash = Hanami::Utils::Hash.new 'a' => 23, 'b' => { 'c' => ['x','y','z'] }
278
- # hash.deep_symbolize!
279
- #
280
- # hash.keys # => [:a, :b]
281
- # hash.inspect # => {:a=>23, :b=>{:c=>["x", "y", "z"]}}
282
- def deep_symbolize!
283
- keys.each do |k|
284
- v = delete(k)
285
- v = self.class.new(v).deep_symbolize! if v.respond_to?(:to_hash)
286
-
287
- self[k.to_sym] = v
288
- end
289
-
290
- self
291
- end
292
-
293
- # Converts in-place all the keys to Symbol instances, nested hashes are converted too.
294
- #
295
- # @return [Hash] self
296
- #
297
- # @since 0.3.2
298
- # @deprecated Use {Hanami::Utils::Hash.stringify}
299
- #
300
- # @example
301
- # require 'hanami/utils/hash'
302
- #
303
- # hash = Hanami::Utils::Hash.new a: 23, b: { c: ['x','y','z'] }
304
- # hash.stringify!
305
- #
306
- # hash.keys # => [:a, :b]
307
- # hash.inspect # => {"a"=>23, "b"=>{"c"=>["x", "y", "z"]}}
308
- def stringify!
309
- keys.each do |k|
310
- v = delete(k)
311
- v = self.class.new(v).stringify! if v.respond_to?(:to_hash)
312
-
313
- self[k.to_s] = v
314
- end
315
-
316
- self
317
- end
318
-
319
- # Returns a deep copy of the current Hanami::Utils::Hash
320
- #
321
- # @return [Hash] a deep duplicated self
322
- #
323
- # @since 0.3.1
324
- # @deprecated Use {Hanami::Utils::Hash.deep_dup}
325
- #
326
- # @example
327
- # require 'hanami/utils/hash'
328
- #
329
- # hash = Hanami::Utils::Hash.new(
330
- # 'nil' => nil,
331
- # 'false' => false,
332
- # 'true' => true,
333
- # 'symbol' => :foo,
334
- # 'fixnum' => 23,
335
- # 'bignum' => 13289301283 ** 2,
336
- # 'float' => 1.0,
337
- # 'complex' => Complex(0.3),
338
- # 'bigdecimal' => BigDecimal('12.0001'),
339
- # 'rational' => Rational(0.3),
340
- # 'string' => 'foo bar',
341
- # 'hash' => { a: 1, b: 'two', c: :three },
342
- # 'u_hash' => Hanami::Utils::Hash.new({ a: 1, b: 'two', c: :three })
343
- # )
344
- #
345
- # duped = hash.deep_dup
346
- #
347
- # hash.class # => Hanami::Utils::Hash
348
- # duped.class # => Hanami::Utils::Hash
349
- #
350
- # hash.object_id # => 70147385937100
351
- # duped.object_id # => 70147385950620
352
- #
353
- # # unduplicated values
354
- # duped['nil'] # => nil
355
- # duped['false'] # => false
356
- # duped['true'] # => true
357
- # duped['symbol'] # => :foo
358
- # duped['fixnum'] # => 23
359
- # duped['bignum'] # => 176605528590345446089
360
- # duped['float'] # => 1.0
361
- # duped['complex'] # => (0.3+0i)
362
- # duped['bigdecimal'] # => #<BigDecimal:7f9ffe6e2fd0,'0.120001E2',18(18)>
363
- # duped['rational'] # => 5404319552844595/18014398509481984)
364
- #
365
- # # it duplicates values
366
- # duped['string'].reverse!
367
- # duped['string'] # => "rab oof"
368
- # hash['string'] # => "foo bar"
369
- #
370
- # # it deeply duplicates Hash, by preserving the class
371
- # duped['hash'].class # => Hash
372
- # duped['hash'].delete(:a)
373
- # hash['hash'][:a] # => 1
374
- #
375
- # duped['hash'][:b].upcase!
376
- # duped['hash'][:b] # => "TWO"
377
- # hash['hash'][:b] # => "two"
378
- #
379
- # # it deeply duplicates Hanami::Utils::Hash, by preserving the class
380
- # duped['u_hash'].class # => Hanami::Utils::Hash
381
- def deep_dup
382
- self.class.new.tap do |result|
383
- @hash.each { |k, v| result[k] = Duplicable.dup(v, &DUPLICATE_LOGIC) }
384
- end
385
- end
386
-
387
- # Returns a new array populated with the keys from this hash
388
- #
389
- # @return [Array] the keys
390
- #
391
- # @since 0.3.0
392
- # @deprecated
393
- #
394
- # @see http://www.ruby-doc.org/core/Hash.html#method-i-keys
395
- def keys
396
- @hash.keys
397
- end
398
-
399
- # Deletes the key-value pair and returns the value from hsh whose key is
400
- # equal to key.
401
- #
402
- # @param key [Object] the key to remove
403
- #
404
- # @return [Object,nil] the value hold by the given key, if present
405
- #
406
- # @since 0.3.0
407
- # @deprecated
408
- #
409
- # @see http://www.ruby-doc.org/core/Hash.html#method-i-keys
410
- def delete(key)
411
- @hash.delete(key)
412
- end
413
-
414
- # Retrieves the value object corresponding to the key object.
415
- #
416
- # @param key [Object] the key
417
- #
418
- # @return [Object,nil] the correspoding value, if present
419
- #
420
- # @since 0.3.0
421
- # @deprecated
422
- #
423
- # @see http://www.ruby-doc.org/core/Hash.html#method-i-5B-5D
424
- def [](key)
425
- @hash[key]
426
- end
427
-
428
- # Associates the value given by value with the key given by key.
429
- #
430
- # @param key [Object] the key to assign
431
- # @param value [Object] the value to assign
432
- #
433
- # @since 0.3.0
434
- # @deprecated
435
- #
436
- # @see http://www.ruby-doc.org/core/Hash.html#method-i-5B-5D-3D
437
- def []=(key, value)
438
- @hash[key] = value
439
- end
440
-
441
- # Returns a Ruby Hash as duplicated version of self
442
- #
443
- # @return [::Hash] the hash
444
- #
445
- # @since 0.3.0
446
- # @deprecated
447
- #
448
- # @see http://www.ruby-doc.org/core/Hash.html#method-i-to_h
449
- def to_h
450
- @hash.each_with_object({}) do |(k, v), result|
451
- v = v.to_h if v.respond_to?(:to_hash)
452
- result[k] = v
453
- end
454
- end
455
-
456
- alias_method :to_hash, :to_h
457
-
458
- # Converts into a nested array of [ key, value ] arrays.
459
- #
460
- # @return [::Array] the array
461
- #
462
- # @since 0.3.0
463
- # @deprecated
464
- #
465
- # @see http://www.ruby-doc.org/core/Hash.html#method-i-to_a
466
- def to_a
467
- @hash.to_a
468
- end
469
-
470
- # Equality
471
- #
472
- # @return [TrueClass,FalseClass]
473
- #
474
- # @since 0.3.0
475
- # @deprecated
476
- def ==(other)
477
- @hash == other.to_h
478
- end
479
-
480
- alias_method :eql?, :==
481
-
482
- # Returns the hash of the internal @hash
483
- #
484
- # @return [Fixnum]
485
- #
486
- # @since 0.3.0
487
- # @deprecated
488
- def hash
489
- @hash.hash
490
- end
491
-
492
- # Returns a string describing the internal @hash
493
- #
494
- # @return [String]
495
- #
496
- # @since 0.3.0
497
- # @deprecated
498
- def inspect
499
- @hash.inspect
500
- end
501
-
502
- # Overrides Ruby's method_missing in order to provide ::Hash interface
503
- #
504
- # @api private
505
- # @since 0.3.0
506
- #
507
- # @raise [NoMethodError] If doesn't respond to the given method
508
- def method_missing(method_name, *args, &blk)
509
- unless respond_to?(method_name)
510
- raise NoMethodError.new(%(undefined method `#{method_name}' for #{@hash}:#{self.class}))
511
- end
512
-
513
- h = @hash.__send__(method_name, *args, &blk)
514
- h = self.class.new(h) if h.is_a?(::Hash)
515
- h
516
- end
517
-
518
- # Overrides Ruby's respond_to_missing? in order to support ::Hash interface
519
- #
520
- # @api private
521
- # @since 0.3.0
522
- def respond_to_missing?(method_name, include_private = false)
523
- @hash.respond_to?(method_name, include_private)
524
- end
525
196
  end
526
197
  end
527
198
  end
@@ -43,7 +43,7 @@ module Hanami
43
43
  end
44
44
  # rubocop:enable Style/ClassVars
45
45
 
46
- # Parses the given JSON paylod
46
+ # Parse the given JSON paylod
47
47
  #
48
48
  # @param payload [String] a JSON payload
49
49
  #
@@ -9,7 +9,7 @@ require "hanami/utils"
9
9
  require "hanami/utils/string"
10
10
 
11
11
  unless defined?(Boolean)
12
- # Defines top level constant Boolean, so it can be easily used by other libraries
12
+ # Define top level constant Boolean, so it can be easily used by other libraries
13
13
  # in coercions DSLs
14
14
  #
15
15
  # @since 0.3.0
@@ -327,7 +327,7 @@ module Hanami
327
327
  # # big complex represented as a string
328
328
  # input = Complex(2, 3)
329
329
  # Hanami::Utils::Kernel.Integer(input) # => TypeError
330
- def self.Integer(arg)
330
+ def self.Integer(arg) # rubocop:disable Metrics/MethodLength
331
331
  super(arg)
332
332
  rescue ArgumentError, TypeError, NoMethodError
333
333
  begin
@@ -418,6 +418,7 @@ module Hanami
418
418
  # input = BasicObject.new
419
419
  # Hanami::Utils::Kernel.BigDecimal(input) # => TypeError
420
420
  #
421
+ # rubocop:disable Metrics/MethodLength
421
422
  def self.BigDecimal(arg, precision = ::Float::DIG)
422
423
  case arg
423
424
  when NilClass # This is only needed by Ruby 2.6
@@ -434,6 +435,7 @@ module Hanami
434
435
  rescue NoMethodError
435
436
  raise TypeError.new "can't convert #{inspect_type_error(arg)}into BigDecimal"
436
437
  end
438
+ # rubocop:enable Metrics/MethodLength
437
439
 
438
440
  # Coerces the argument to be a Float.
439
441
  #
@@ -547,7 +549,7 @@ module Hanami
547
549
  # # big complex represented as a string
548
550
  # input = Complex(2, 3)
549
551
  # Hanami::Utils::Kernel.Float(input) # => TypeError
550
- def self.Float(arg)
552
+ def self.Float(arg) # rubocop:disable Metrics/MethodLength
551
553
  super(arg)
552
554
  rescue ArgumentError, TypeError
553
555
  begin
@@ -736,8 +738,7 @@ module Hanami
736
738
  # require 'hanami/utils/kernel'
737
739
  #
738
740
  # Hanami::Utils::Kernel.DateTime(3483943)
739
- # # => Time.at(3483943).to_datetime
740
- # # #<DateTime: 1970-02-10T08:45:43+01:00 ((2440628j,27943s,0n),+3600s,2299161j)>
741
+ # # => Time.at(3483943).to_datetime #<DateTime: 1970-02-10T08:45:43+01:00 ((2440628j,27943s,0n),+3600s,2299161j)>
741
742
  #
742
743
  # Hanami::Utils::Kernel.DateTime(DateTime.now)
743
744
  # # => #<DateTime: 2014-04-18T09:33:49+02:00 ((2456766j,27229s,690849000n),+7200s,2299161j)>
@@ -897,7 +898,7 @@ module Hanami
897
898
  # # Missing #respond_to?
898
899
  # input = BasicObject.new
899
900
  # Hanami::Utils::Kernel.Boolean(input) # => TypeError
900
- def self.Boolean(arg)
901
+ def self.Boolean(arg) # rubocop:disable Metrics/MethodLength
901
902
  case arg
902
903
  when Numeric
903
904
  arg.to_i == BOOLEAN_TRUE_INTEGER
@@ -1022,7 +1023,7 @@ module Hanami
1022
1023
  raise TypeError.new "can't convert #{inspect_type_error(arg)}into Symbol"
1023
1024
  end
1024
1025
 
1025
- # Checks if the given argument is a string representation of a number
1026
+ # Check if the given argument is a string representation of a number
1026
1027
  #
1027
1028
  # @param arg [Object] the input
1028
1029
  #
@@ -1043,11 +1044,11 @@ module Hanami
1043
1044
  # @since 0.4.3
1044
1045
  # @api private
1045
1046
  def self.inspect_type_error(arg)
1046
- (arg.respond_to?(:inspect) ? arg.inspect : arg.to_s) + " "
1047
- rescue NoMethodError
1047
+ (arg.respond_to?(:inspect) ? arg.inspect : arg.to_s) << " "
1048
+ rescue NoMethodError => _
1048
1049
  # missing the #respond_to? method, fall back to returning the class' name
1049
1050
  begin
1050
- arg.class.name + " instance "
1051
+ arg.class.name << " instance "
1051
1052
  rescue NoMethodError
1052
1053
  # missing the #class method, can't fall back to anything better than nothing
1053
1054
  # Callers will have to guess from their code
@@ -1056,7 +1057,7 @@ module Hanami
1056
1057
  end
1057
1058
 
1058
1059
  class << self
1059
- private :inspect_type_error
1060
+ private :inspect_type_error # rubocop:disable Style/AccessModifierDeclarations
1060
1061
  end
1061
1062
  end
1062
1063
  end