darthjee-core_ext 1.7.4 → 3.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.
Files changed (101) hide show
  1. checksums.yaml +5 -5
  2. data/.circleci/config.yml +63 -9
  3. data/.gitignore +2 -0
  4. data/.reek.yml +3 -0
  5. data/.rubocop.yml +18 -1
  6. data/.rubocop_todo.yml +15 -8
  7. data/ARRAY_README.md +72 -15
  8. data/CLASS_README.md +154 -0
  9. data/DATE_README.md +19 -9
  10. data/Dockerfile +18 -5
  11. data/ENUMERABLE_README.md +154 -4
  12. data/Gemfile +13 -0
  13. data/HASH_README.md +276 -135
  14. data/MATH_README.md +14 -10
  15. data/Makefile +7 -0
  16. data/OBJECT_README.md +18 -35
  17. data/README.md +12 -4
  18. data/Rakefile +1 -0
  19. data/SYMBOL_README.md +13 -18
  20. data/config/check_specs.yml +20 -0
  21. data/config/rubycritc.rb +12 -0
  22. data/config/yardstick.yml +45 -3
  23. data/core_ext.gemspec +10 -18
  24. data/docker-compose.yml +24 -7
  25. data/lib/darthjee/core_ext/array/hash_builder.rb +22 -5
  26. data/lib/darthjee/core_ext/array.rb +22 -14
  27. data/lib/darthjee/core_ext/class.rb +29 -10
  28. data/lib/darthjee/core_ext/date.rb +1 -0
  29. data/lib/darthjee/core_ext/enumerable.rb +67 -29
  30. data/lib/darthjee/core_ext/hash/cameliazable.rb +52 -21
  31. data/lib/darthjee/core_ext/hash/chain_fetcher.rb +18 -1
  32. data/lib/darthjee/core_ext/hash/changeable.rb +88 -0
  33. data/lib/darthjee/core_ext/hash/deep_hash_constructor/setter.rb +112 -0
  34. data/lib/darthjee/core_ext/hash/deep_hash_constructor.rb +127 -62
  35. data/lib/darthjee/core_ext/hash/key_changeable.rb +138 -66
  36. data/lib/darthjee/core_ext/hash/key_changer.rb +146 -45
  37. data/lib/darthjee/core_ext/hash/keys_sorter.rb +43 -6
  38. data/lib/darthjee/core_ext/hash/squasher.rb +131 -18
  39. data/lib/darthjee/core_ext/hash/transformable.rb +133 -41
  40. data/lib/darthjee/core_ext/hash/transposeable.rb +37 -8
  41. data/lib/darthjee/core_ext/hash/value_changer.rb +76 -36
  42. data/lib/darthjee/core_ext/hash.rb +6 -4
  43. data/lib/darthjee/core_ext/math.rb +37 -6
  44. data/lib/darthjee/core_ext/numeric.rb +13 -2
  45. data/lib/darthjee/core_ext/object.rb +27 -0
  46. data/lib/darthjee/core_ext/symbol.rb +22 -2
  47. data/lib/darthjee/core_ext/version.rb +1 -1
  48. data/scripts/check_readme.sh +6 -0
  49. data/scripts/rubycritic.sh +10 -0
  50. data/spec/integration/readme/array_spec.rb +96 -0
  51. data/spec/integration/readme/class_spec.rb +123 -0
  52. data/spec/integration/readme/date_spec.rb +20 -0
  53. data/spec/integration/readme/enumerable_spec.rb +87 -0
  54. data/spec/integration/readme/hash_spec.rb +400 -0
  55. data/spec/integration/readme/math_spec.rb +31 -0
  56. data/spec/integration/readme/object_spec.rb +49 -0
  57. data/spec/integration/readme/symbol_spec.rb +29 -0
  58. data/spec/integration/yard/darthjee/core_ext/array_spec.rb +1 -1
  59. data/spec/integration/yard/darthjee/core_ext/class/default_value_spec.rb +10 -8
  60. data/spec/integration/yard/darthjee/core_ext/enumerable_spec.rb +24 -4
  61. data/spec/integration/yard/darthjee/core_ext/hash/cameliazable_spec.rb +11 -0
  62. data/spec/integration/yard/darthjee/core_ext/hash/changeable_spec.rb +68 -0
  63. data/spec/integration/yard/darthjee/core_ext/hash/deep_hash_constructor/setter_spec.rb +34 -0
  64. data/spec/integration/yard/darthjee/core_ext/hash/deep_hash_constructor_spec.rb +65 -0
  65. data/spec/integration/yard/darthjee/core_ext/hash/key_changeable_spec.rb +8 -0
  66. data/spec/integration/yard/darthjee/core_ext/hash/key_changer_spec.rb +59 -0
  67. data/spec/integration/yard/darthjee/core_ext/hash/keys_sorter_spec.rb +25 -0
  68. data/spec/integration/yard/darthjee/core_ext/hash/squasher_spec.rb +60 -0
  69. data/spec/integration/yard/darthjee/core_ext/hash/transformable_spec.rb +67 -37
  70. data/spec/integration/yard/darthjee/core_ext/hash/transposeable_spec.rb +35 -0
  71. data/spec/integration/yard/darthjee/core_ext/hash/value_changer_spec.rb +1 -1
  72. data/spec/integration/yard/darthjee/core_ext/hash_spec.rb +13 -2
  73. data/spec/integration/yard/darthjee/core_ext/math_spec.rb +28 -0
  74. data/spec/integration/yard/darthjee/core_ext/numeric_spec.rb +11 -0
  75. data/spec/integration/yard/darthjee/core_ext/object_spec.rb +47 -0
  76. data/spec/integration/yard/darthjee/core_ext/symbol_spec.rb +17 -0
  77. data/spec/lib/array_spec.rb +2 -1
  78. data/spec/lib/darthjee/core_ext/hash/deep_hash_constructor/setter_spec.rb +64 -0
  79. data/spec/lib/darthjee/core_ext/hash/deep_hash_constructor_spec.rb +16 -156
  80. data/spec/lib/darthjee/core_ext/hash/keys_sorter_spec.rb +5 -4
  81. data/spec/lib/darthjee/core_ext/hash/squasher_spec.rb +8 -2
  82. data/spec/lib/darthjee/core_ext/hash/value_changer_spec.rb +5 -13
  83. data/spec/lib/hash_spec.rb +87 -147
  84. data/spec/lib/object_spec.rb +32 -0
  85. data/spec/lib/symbol_spec.rb +2 -2
  86. data/spec/spec_helper.rb +4 -2
  87. data/spec/support/models/client.rb +23 -0
  88. data/spec/support/models/dummy_iterator.rb +4 -4
  89. data/spec/support/models/hash/value_changer/dummy.rb +1 -0
  90. data/spec/support/shared_examples/array/array_random.rb +2 -3
  91. data/spec/support/shared_examples/hash/chain_hash_keys_changer.rb +1 -1
  92. data/spec/support/shared_examples/hash/deep_hash.rb +166 -0
  93. data/spec/support/shared_examples/hash/hash_keys_changer.rb +3 -3
  94. data/spec/support/shared_examples/hash/hash_squasher.rb +54 -9
  95. data/spec/support/shared_examples/hash/keys_sorter.rb +266 -6
  96. data/spec/support/shared_examples/hash/map_to_hash.rb +1 -1
  97. data/spec/support/shared_examples/hash/remap.rb +4 -4
  98. data/spec/support/shared_examples/hash/value_changer.rb +2 -2
  99. metadata +41 -189
  100. data/lib/darthjee/core_ext/hash/to_hash_mapper.rb +0 -25
  101. data/spec/lib/darthjee/core_ext/hash/to_hash_mapper_spec.rb +0 -11
@@ -7,14 +7,26 @@ module Darthjee
7
7
  # changing / transforming keys of a Hash
8
8
  #
9
9
  # @api public
10
+ #
11
+ # @author Darthjee
12
+ #
13
+ # @see KeyChanger
14
+ # @see KeysSorter
10
15
  module KeyChangeable
11
- # Change all keys by publically sending methods to the keys without
12
- # changing the original hash
16
+ ##########################################
17
+ # Key change methods
18
+ ##########################################
19
+
20
+ # Change all keys without changing the original hash
21
+ #
22
+ # It changes all keysby publically sending methods
23
+ # to the keys
13
24
  #
14
25
  # @return [::Hash] New hash with the resulting keys
15
- # @param [::Array<Symbol>] calls methods to be called form the key`
26
+ # @param [::Array<Symbol>] calls methods to be
27
+ # called form the key`
16
28
  #
17
- # @see #change_keys
29
+ # @see #chain_change_keys!
18
30
  #
19
31
  # @example
20
32
  # hash = { first: 1, second: 2 }
@@ -24,20 +36,22 @@ module Darthjee
24
36
  deep_dup.chain_change_keys!(*calls)
25
37
  end
26
38
 
27
- # Change all keys by publically sending methods to the keys
28
- # changing the original hash
39
+ # Change all keys changing the original hash
40
+ #
41
+ # It changes all keys by publically sending methods
42
+ # to the keys
29
43
  #
30
44
  # @return [::Hash] New hash with the resulting keys
31
45
  # @param [::Array<Symbol>] calls methods to be called form the key`
32
46
  #
33
- # @see #chain_change_keys
47
+ # @see #change_keys
34
48
  #
35
49
  # @example (see #chain_change_keys)
36
50
  def chain_change_keys!(*calls)
37
51
  options = calls.extract_options!
38
52
 
39
53
  calls.inject(self) do |h, m|
40
- h.change_keys!(options, &m)
54
+ h.change_keys!(**options, &m)
41
55
  end
42
56
  end
43
57
 
@@ -45,10 +59,13 @@ module Darthjee
45
59
  #
46
60
  # @return new Hash with modified keys
47
61
  # @param [::Hash] options options to passed to KeyChanger
48
- # @option options [Boolean] recursive: flag defining the
62
+ # @option options [::TrueClass,::FalseClass]
63
+ # recursive (true) flag defining the
49
64
  # change to happen also
50
65
  # on inner hashes (defaults to: true)
51
66
  #
67
+ # @yield (key) changing key block
68
+ #
52
69
  # @see Hash::KeyChanger#change_keys
53
70
  #
54
71
  # @example
@@ -63,78 +80,116 @@ module Darthjee
63
80
  # (k.to_i + 1).to_s.to_sym
64
81
  # end
65
82
  # result # returns { :'2' => 1, :'3' => { '3' => 2 } }
66
- def change_keys(options = {}, &block)
67
- deep_dup.change_keys!(options, &block)
83
+ def change_keys(**, &)
84
+ deep_dup.change_keys!(**, &)
68
85
  end
69
86
 
70
87
  # Change all keys modifying and returning the hash
71
88
  #
72
89
  # @return self
73
90
  # @param [::Hash] options options to passed to KeyChanger
74
- # @option options [Boolean] recursive: flag defining the
91
+ # @option options [::TrueClass,::FalseClass]
92
+ # recursive: (true) flag defining the
75
93
  # change to happen also
76
94
  # on inner hashes (defaults to: true)
77
95
  #
96
+ # @yield (key) changing key block
97
+ #
78
98
  # @see Hash::KeyChanger#change_keys
79
99
  #
80
100
  # @example (see #change_keys)
81
- def change_keys!(options = {}, &block)
82
- Hash::KeyChanger.new(self).change_keys(options, &block)
101
+ def change_keys!(**, &)
102
+ Hash::KeyChanger.new(self).change_keys(**, &)
83
103
  end
84
104
 
85
105
  # prepend a string to all keys
86
- # options {
87
- # recursive: true,
88
- # type: :keep [keep, string, symbol] (key type to be returned)
89
- # }
90
- # ex: { :a => 1, "b"=> 2 }.prepend_to_keys("foo_")
91
- # # returns { :foo_a => 1, "foo_b"=> 2 }
92
- def prepend_to_keys(str, options = {})
93
- change_key_text(options) do |key|
106
+ #
107
+ # @param options [::Hash]
108
+ # @option options [::TrueClass,::FalseClass]
109
+ # recursive (true)
110
+ # flag indicating transformation should be recursive
111
+ # @option options [::Symbol] type (:keep)
112
+ # type of the final key
113
+ # - keep : cast the result to the same type of the
114
+ # original key
115
+ # - string : cast the result to be {::String}
116
+ # - symbol cast the result to be {::Symbol}
117
+ #
118
+ # @return [::Hash]
119
+ #
120
+ # @see KeyChanger#change_keys
121
+ #
122
+ # @example
123
+ # hash = { :a => 1, "b"=> 2 }
124
+ #
125
+ # hash.prepend_to_keys("foo_") # returns {
126
+ # # :foo_a => 1,
127
+ # # "foo_b"=> 2
128
+ # # }
129
+ def prepend_to_keys(str, **)
130
+ change_key_text(**) do |key|
94
131
  "#{str}#{key}"
95
132
  end
96
133
  end
97
134
 
98
- # append a string to all keys
99
- # options {
100
- # recursive: true,
101
- # type: :keep [keep, string, symbol] (key type to be returned)
102
- # }
103
- # ex: { :a => 1, "b"=> 2 }.append_to_keys("_bar")
104
- # # returns { :a_bar => 1, "b_bar"=> 2 }
105
- def append_to_keys(str, options = {})
106
- change_key_text(options) do |key|
135
+ # Append a string to all keys
136
+ #
137
+ # @param options [::Hash]
138
+ # @option options [::TrueClass,::FalseClass]
139
+ # recursive (true)
140
+ # flag indicating transformation should be recursive
141
+ # @option options [::Symbol] type (:keep)
142
+ # type of the final key
143
+ # - keep : cast the result to the same type of the
144
+ # original key
145
+ # - string : cast the result to be {::String}
146
+ # - symbol cast the result to be {::Symbol}
147
+ #
148
+ # @return [::Hash]
149
+ #
150
+ # @see KeyChanger#change_keys
151
+ #
152
+ # @example (see #prepend_to_keys)
153
+ def append_to_keys(str, **)
154
+ change_key_text(**) do |key|
107
155
  "#{key}#{str}"
108
156
  end
109
157
  end
110
158
 
111
- # sorts keys for hash
112
- # options: { recursive: true }
113
- # ex: { b:1, a:2 }.sort_keys == { a:2, b:1 }
114
- def sort_keys(options = {})
115
- Hash::KeysSorter.new(self, **options).sort
116
- end
117
-
118
- ##########################################
119
- # Value change methods
120
- ##########################################
121
-
122
- # creates a new hash with changes in its values
123
- # options: {
124
- # recursive: true,
125
- # skip_hash:true
126
- # }
127
- # ex: { a:1, b:2 }.change_values{ |v| v+1 } == { a:2, b:3 }
128
- # ex: { a:1, b:{ c:1 } }.change_values(skip_hash:false) { |v| v.to_s }
129
- # # returns { a:"1", b:"{ c=>1 }
130
- # ex: { a:1, b:{ c:1 } }.change_values(skip_hash:true) { |v| v.to_s }
131
- # # returns { a:"1", b:{ c=>"1" } }
132
- def change_values(options = {}, &block)
133
- deep_dup.change_values!(options, &block)
159
+ # Sorts keys for hash changing the original
160
+ #
161
+ # @param options [::Hash]
162
+ # @option options [::TrueClass,::FalseClass]
163
+ # recursive (true) flag indicating recursive sorting
164
+ #
165
+ # @return [::Hash]
166
+ #
167
+ # @see KeySorter#sort
168
+ #
169
+ # @example
170
+ # hash = { b: 1, a: 2 }
171
+ #
172
+ # hash.sort_keys # changes hash to { a: 2, b: 1 }
173
+ def sort_keys!(**)
174
+ Hash::KeysSorter.new(self, **).sort
134
175
  end
135
176
 
136
- def change_values!(options = {}, &block)
137
- Hash::ValueChanger.new(options, &block).change(self)
177
+ # Sorts keys for hash without changing the original
178
+ #
179
+ # @param options [::Hash]
180
+ # @option options [::TrueClass,::FalseClass]
181
+ # recursive (true) flag indicating recursive sorting
182
+ #
183
+ # @return [::Hash]
184
+ #
185
+ # @see KeySorter#sort
186
+ #
187
+ # @example
188
+ # hash = { b: 1, a: 2 }
189
+ #
190
+ # hash.sort_keys # returns { a: 2, b: 1 }
191
+ def sort_keys(**)
192
+ Hash::KeysSorter.new(deep_dup, **).sort
138
193
  end
139
194
 
140
195
  # Changes the key of the hash without changing it
@@ -143,7 +198,10 @@ module Darthjee
143
198
  #
144
199
  # @example
145
200
  # hash = { a: 1, b: 2 }
146
- # hash.remap_keys(a: :b, b: :c) # returns { b: 1, c: 2 }
201
+ # hash.remap_keys(a: :b, b: :c) # returns {
202
+ # # b: 1,
203
+ # # c: 2
204
+ # # }
147
205
  def remap_keys(remap)
148
206
  dup.remap_keys!(remap)
149
207
  end
@@ -159,15 +217,29 @@ module Darthjee
159
217
 
160
218
  private
161
219
 
162
- # changes the text of the keys
163
- # options {
164
- # recursive: true,
165
- # type: :keep [keep, string, symbol] (key type to be returned)
166
- # }
167
- # ex: { :a => 1, "b"=> 2 }.change_key_text{ |key| key.upcase }
168
- # # returns { :A => 1, "B"=> 2 }
169
- def change_key_text(options = {}, &block)
170
- Hash::KeyChanger.new(self).change_text(options, &block)
220
+ # @private
221
+ # @api private
222
+ #
223
+ # Changes the text of the keys
224
+ #
225
+ # @param options [::Hash]
226
+ # @option options [::TrueClass,::FalseClass]
227
+ # recursive (true)
228
+ # flag indicating transformation should be recursive
229
+ # @option options [::Symbol] type (:keep)
230
+ # type of the final key
231
+ # - keep : cast the result to the same type of the
232
+ # original key
233
+ # - string : cast the result to be {::String}
234
+ # - symbol cast the result to be {::Symbol}
235
+ #
236
+ # @yield (key) changing key block
237
+ #
238
+ # @return [::Hash]
239
+ #
240
+ # @see KeyChanger
241
+ def change_key_text(**, &)
242
+ Hash::KeyChanger.new(self).change_text(**, &)
171
243
  end
172
244
  end
173
245
  end
@@ -4,11 +4,34 @@ module Darthjee
4
4
  module CoreExt
5
5
  module Hash
6
6
  # @api private
7
+ #
8
+ # @author Darthjee
7
9
  class KeyChanger
8
10
  def initialize(hash)
9
11
  @hash = hash
10
12
  end
11
13
 
14
+ # Changes keys based on map
15
+ #
16
+ # @param keys_map [::Hash] map of
17
+ # original => final key
18
+ #
19
+ # @return [::Hash] the given hash modified
20
+ #
21
+ # @example
22
+ # hash = { a: 1, 'b' => 2 }
23
+ # changer = Darthjee::CoreExt::Hash::KeyChanger.new(hash)
24
+ # remap_map = { a: 1, 'b' => 2 }
25
+ #
26
+ # changer.remap(remap_map)
27
+ #
28
+ # hash # changed to {
29
+ # # za: 1,
30
+ # # 'yb' => 2,
31
+ # # zb: nil
32
+ # # }
33
+ #
34
+ # @example (see Hash::KeyChangeable#remap_keys)
12
35
  def remap(keys_map)
13
36
  new_hash = {}
14
37
  keys_map.each do |o, n|
@@ -19,57 +42,110 @@ module Darthjee
19
42
 
20
43
  # Change the keys of the given hash returning the new hash
21
44
  #
22
- # @return New hash after keys tranformation
45
+ # @param [::TrueClass,::FalseClass]
46
+ # recursive flag defining
47
+ # the change to happen also on inner hashes
23
48
  #
24
- # @param [::Hash] options options for transformation
25
- # @option options [Boolean] recursive: flag defining
26
- # the change to happen also
27
- # on inner hashes (defaults to: true)
49
+ # @return [::Hash] Given hash after keys tranformation
28
50
  #
29
- # @example (see Hash#change_keys)
30
- def change_keys(options = {}, &block)
31
- options = {
32
- recursive: true
33
- }.merge!(options)
34
-
35
- if options[:recursive]
36
- hash.deep_transform_keys!(&block)
51
+ # @example (see Hash::KeyChangeable#change_keys)
52
+ #
53
+ # @example
54
+ # hash = { a: 1, 'b' => { c: 3 } }
55
+ # changer = Darthjee::CoreExt::Hash::KeyChanger.new(hash)
56
+ # changer.change_keys { |k| "key_#{k}" }
57
+ #
58
+ # hash # changed to {
59
+ # # 'key_a' => 1,
60
+ # # 'key_b' => {
61
+ # # 'key_c' => 3
62
+ # # }
63
+ # # }
64
+ def change_keys(recursive: true, &)
65
+ if recursive
66
+ hash.deep_transform_keys!(&)
37
67
  else
38
- hash.transform_keys!(&block)
68
+ hash.transform_keys!(&)
39
69
  end
40
70
  end
41
71
 
42
72
  # Performs camelization of the keys of the hash
43
73
  #
44
- # @return [::Hash] the given hash with it's keys changed
45
- # @param [::Hash] options options
46
- # @option options [::Boolean] uppercase_first_letter: flag
74
+ # @param [::Hash] options
75
+ # @param [::TrueClass,::FalseClass]
76
+ # uppercase_first_letter flag
47
77
  # defining the type of CamelCase
78
+ # @option options [::TrueClass,::FalseClass]
79
+ # recursive (true) flag defining
80
+ # the change to happen also on inner hashes
48
81
  #
49
- # @example (see Hash#camelize_keys)
50
- def camelize_keys(options = {})
51
- options = {
52
- uppercase_first_letter: true
53
- }.merge!(options)
54
-
55
- type = options[:uppercase_first_letter] ? :upper : :lower
82
+ # @return [::Hash] the given hash with it's keys
83
+ # changed
84
+ #
85
+ # @see #change_keys
86
+ # @see Cameliazable#camelize_keys
87
+ #
88
+ # @example (see Cameliazable#camelize_keys)
89
+ #
90
+ # @example
91
+ # hash = { my_key: { inner_key: 10 } }
92
+ # changer = Darthjee::CoreExt::Hash::KeyChanger.new(hash)
93
+ # changer.camelize_keys
94
+ # hash # changed to { MyKey: { InnerKey: 10 } }
95
+ def camelize_keys(uppercase_first_letter: true, **)
96
+ type = uppercase_first_letter ? :upper : :lower
56
97
 
57
- change_keys(options) do |k|
58
- k.camelize(type)
98
+ change_keys(**) do |key|
99
+ key.camelize(type)
59
100
  end
60
101
  end
61
102
 
62
- def underscore_keys(options = {})
63
- change_keys(options, &:underscore)
103
+ # Changes keys by performing underscore transformation
104
+ #
105
+ # @param [::hash] options
106
+ # @option options [::TrueClass,::FalseClass]
107
+ # recursive (true) flag defining
108
+ # the change to happen also on inner hashes
109
+ #
110
+ # @return [::Hash]
111
+ #
112
+ # @example (see Cameliazable#underscore_keys)
113
+ #
114
+ # @example
115
+ # hash = { myKey: { InnerKey: 10 } }
116
+ # changer = Darthjee::CoreExt::Hash::KeyChanger.new(hash)
117
+ # changer.underscore_keys
118
+ #
119
+ # hash # changed to { my_key: { inner_key: 10 } }
120
+ def underscore_keys(**)
121
+ change_keys(**, &:underscore)
64
122
  end
65
123
 
66
- def change_text(options = {})
67
- options = {
68
- type: :keep
69
- }.merge!(options)
70
-
71
- change_keys(options) do |key|
72
- cast_new_key yield(key), key.class, options
124
+ # Change keys considering them to be strings
125
+ #
126
+ # @param options [::Hash]
127
+ # @param type [::Symbol] type that key will be case
128
+ # - keep: Cast the key back to the same type it was
129
+ # - string cast the key to {String}
130
+ # - symbol cast the key to {Symbol}
131
+ #
132
+ # @option options [::TrueClass,::FalseClass]
133
+ # recursive (true) flag defining
134
+ # the change to happen also on inner hashes
135
+ #
136
+ # @yield (key) key transformation block
137
+ #
138
+ # @return [::Hash] the given hash with changed keys
139
+ #
140
+ # @example
141
+ # hash = { key: { inner_key: 10 } }
142
+ # changer = Darthjee::CoreExt::Hash::KeyChanger.new(hash)
143
+ # changer.change_text { |key| key.to_s.upcase }
144
+ #
145
+ # hash # changed to { KEY: { INNER_KEY: 10 } }
146
+ def change_text(type: :keep, **)
147
+ change_keys(**) do |key|
148
+ cast_new_key yield(key), key.class, type
73
149
  end
74
150
  end
75
151
 
@@ -77,22 +153,47 @@ module Darthjee
77
153
 
78
154
  attr_reader :hash
79
155
 
80
- def cast_new_key(key, old_clazz, options)
81
- case class_cast(old_clazz, options)
82
- when :symbol then
156
+ # @api private
157
+ # @private
158
+ #
159
+ # Cast key to correct type (String or Symbol)
160
+ #
161
+ # @param key [::String] key to be cast
162
+ # (after transformation)
163
+ # @param old_clazz [::Class] original class of the key
164
+ # @param type [::Symbol] option of type
165
+ # - keep: Cast the key back to the same type it was
166
+ # - string cast the key to {String}
167
+ # - symbol cast the key to {Symbol}
168
+ #
169
+ # @return [::String,::Symbol]
170
+ def cast_new_key(key, old_clazz, type)
171
+ case class_cast(old_clazz, type)
172
+ when :symbol
83
173
  key.to_sym
84
- when :string then
174
+ when :string
85
175
  key.to_s
86
176
  end
87
177
  end
88
178
 
89
- def keep_class?(options)
90
- options[:type] == :keep
91
- end
179
+ # @api private
180
+ # @private
181
+ #
182
+ # Returns the type of the cast to be applied
183
+ #
184
+ # @param old_clazz [::Class] original class of a key
185
+ # @param type [:symbol] option of castying
186
+ # - keep: Cast the key back to the same type it was
187
+ # - string cast the key to {String}
188
+ # - symbol cast the key to {Symbol}
189
+ #
190
+ # @see #cast_new_key
191
+ #
192
+ # @return [::Symbol]
193
+ def class_cast(old_clazz, type)
194
+ return type unless type == :keep
92
195
 
93
- def class_cast(old_clazz, options)
94
- klass = keep_class?(options) && old_clazz.to_s.downcase.to_sym
95
- klass || options[:type]
196
+ old_clazz.to_s.downcase.to_sym
96
197
  end
97
198
  end
98
199
  end
@@ -3,32 +3,69 @@
3
3
  module Darthjee
4
4
  module CoreExt
5
5
  module Hash
6
+ # @api private
7
+ #
8
+ # @author Darthjee
9
+ #
10
+ # Class responsible for sorting keys of a Hash
6
11
  class KeysSorter
12
+ # @param hash [::hash] hash to be sorted
13
+ # @param recursive [::TrueClass,::FalseClass]
14
+ # flag indicating to perform transformation
15
+ # recursively
7
16
  def initialize(hash, recursive: true)
8
17
  @hash = hash
9
18
  @recursive = recursive
10
19
  end
11
20
 
21
+ # Creates a new Hash sorting it's keys
22
+ #
23
+ # @return [::Hash] new hash
24
+ #
25
+ # @example (see KeyChangeable#sort_keys)
26
+ #
27
+ # @example Simple Usage
28
+ # hash = { key: 10, a_key: { z: 5, a: 10 } }
29
+ # sorter = Darthjee::CoreExt::Hash::KeysSorter.new(hash)
30
+ #
31
+ # sorter.sort # changes hash to {
32
+ # # a_key: { a: 10, z: 5 },
33
+ # # key: 10
34
+ # # }
12
35
  def sort
13
- {}.tap do |new_hash|
36
+ hash.tap do
14
37
  sorted_keys.each do |key|
15
- new_hash[key] = change_value(hash[key])
38
+ hash[key] = change_value(hash.delete(key))
16
39
  end
17
40
  end
18
41
  end
19
42
 
20
43
  private
21
44
 
45
+ attr_reader :hash, :recursive
46
+
47
+ # @api private
48
+ # @private
49
+ #
50
+ # Returns all keys sorted
51
+ #
52
+ # @return [::Array<::Object>]
22
53
  def sorted_keys
23
54
  hash.keys.sort
24
55
  end
25
56
 
57
+ # @api private
58
+ # @private
59
+ #
60
+ # Applies recursion when needed
61
+ #
62
+ # @return [::Object]
26
63
  def change_value(value)
27
- return value unless value.is_a?(Hash) && recursive
28
- value.sort_keys(recursive: true)
29
- end
64
+ return value unless recursive
65
+ return value unless value.is_a?(Hash)
30
66
 
31
- attr_reader :hash, :recursive
67
+ self.class.new(value).sort
68
+ end
32
69
  end
33
70
  end
34
71
  end