hanami-utils 1.3.7 → 2.0.0.alpha1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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