darthjee-core_ext 1.7.3 → 1.7.4

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 (67) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +19 -8
  3. data/.gitignore +1 -0
  4. data/.rubocop.yml +7 -0
  5. data/.rubocop_todo.yml +7 -3
  6. data/Dockerfile +9 -0
  7. data/README.md +5 -6
  8. data/Rakefile +2 -0
  9. data/config/yardstick.rb +13 -0
  10. data/config/yardstick.yml +35 -0
  11. data/core_ext.gemspec +9 -7
  12. data/docker-compose.yml +3 -6
  13. data/lib/darthjee/core_ext/array.rb +2 -2
  14. data/lib/darthjee/core_ext/class.rb +90 -4
  15. data/lib/darthjee/core_ext/enumerable.rb +5 -1
  16. data/lib/darthjee/core_ext/hash.rb +30 -0
  17. data/lib/darthjee/core_ext/hash/cameliazable.rb +91 -0
  18. data/lib/darthjee/core_ext/hash/chain_fetcher.rb +10 -0
  19. data/lib/darthjee/core_ext/hash/key_changeable.rb +85 -53
  20. data/lib/darthjee/core_ext/hash/key_changer.rb +41 -31
  21. data/lib/darthjee/core_ext/hash/value_changer.rb +128 -11
  22. data/lib/darthjee/core_ext/version.rb +1 -1
  23. data/spec/integration/yard/{array → darthjee/core_ext/array}/hash_builder_spec.rb +3 -3
  24. data/spec/integration/yard/{array_spec.rb → darthjee/core_ext/array_spec.rb} +0 -0
  25. data/spec/integration/yard/darthjee/core_ext/class/default_value_spec.rb +143 -0
  26. data/spec/integration/yard/{date → darthjee/core_ext/date}/days_between_spec.rb +6 -6
  27. data/spec/integration/yard/{enumerable_spec.rb → darthjee/core_ext/enumerable_spec.rb} +0 -0
  28. data/spec/integration/yard/darthjee/core_ext/hash/cameliazable_spec.rb +34 -0
  29. data/spec/integration/yard/darthjee/core_ext/hash/chain_fetcher_spec.rb +51 -0
  30. data/spec/integration/yard/darthjee/core_ext/hash/key_changeable_spec.rb +48 -0
  31. data/spec/integration/yard/{hash → darthjee/core_ext/hash}/transformable_spec.rb +7 -3
  32. data/spec/integration/yard/darthjee/core_ext/hash/value_changer_spec.rb +66 -0
  33. data/spec/integration/yard/darthjee/core_ext/hash_spec.rb +42 -0
  34. data/spec/lib/array_spec.rb +27 -17
  35. data/spec/lib/class_spec.rb +108 -7
  36. data/spec/lib/darthjee/core_ext/hash/deep_hash_constructor_spec.rb +1 -1
  37. data/spec/lib/darthjee/core_ext/hash/key_changer_spec.rb +8 -8
  38. data/spec/lib/darthjee/core_ext/hash/keys_sorter_spec.rb +1 -0
  39. data/spec/lib/darthjee/core_ext/hash/to_hash_mapper_spec.rb +1 -0
  40. data/spec/lib/darthjee/core_ext/hash/value_changer_spec.rb +246 -0
  41. data/spec/lib/date_spec.rb +5 -4
  42. data/spec/lib/hash_spec.rb +45 -32
  43. data/spec/lib/math_spec.rb +1 -0
  44. data/spec/lib/numeric_spec.rb +39 -17
  45. data/spec/lib/object_spec.rb +7 -7
  46. data/spec/lib/symbol_spec.rb +2 -2
  47. data/spec/lib/time_spec.rb +5 -4
  48. data/spec/support/models/default_reader_model.rb +8 -0
  49. data/spec/support/models/default_value_model.rb +2 -0
  50. data/spec/support/models/dummy_iterator.rb +15 -0
  51. data/spec/support/models/dummy_transformer.rb +15 -0
  52. data/spec/support/shared_examples/array/array_random.rb +2 -1
  53. data/spec/support/shared_examples/clean.rb +20 -20
  54. data/spec/support/shared_examples/date.rb +18 -13
  55. data/spec/support/shared_examples/hash/chain_fetch.rb +4 -3
  56. data/spec/support/shared_examples/hash/chain_hash_keys_changer.rb +14 -7
  57. data/spec/support/shared_examples/hash/hash_keys_changer.rb +10 -4
  58. data/spec/support/shared_examples/hash/hash_transpose.rb +1 -1
  59. data/spec/support/shared_examples/hash/keys_appender.rb +14 -4
  60. data/spec/support/shared_examples/hash/keys_camelizer.rb +7 -7
  61. data/spec/support/shared_examples/hash/keys_sorter.rb +3 -3
  62. data/spec/support/shared_examples/hash/keys_underscorer.rb +2 -2
  63. data/spec/support/shared_examples/hash/map_to_hash.rb +14 -12
  64. data/spec/support/shared_examples/hash/remap.rb +4 -4
  65. data/spec/support/shared_examples/hash/value_changer.rb +40 -33
  66. metadata +70 -20
  67. data/spec/integration/yard/class/default_value_spec.rb +0 -58
@@ -3,6 +3,11 @@
3
3
  module Darthjee
4
4
  module CoreExt
5
5
  module Hash
6
+ # Class responsible for running ::Hash#chain_fetch
7
+ #
8
+ # @api private
9
+ #
10
+ # @see Darthjee::CoreExt::Hash#chain_fetch
6
11
  class ChainFetcher
7
12
  def initialize(hash, *keys, &block)
8
13
  @hash = hash
@@ -10,6 +15,11 @@ module Darthjee
10
15
  @block = block
11
16
  end
12
17
 
18
+ # Crawls through the hash fetching the keys in chain
19
+ #
20
+ # @example (see Darthjee::CoreExt::Hash#chain_fetch)
21
+ #
22
+ # @return [Object] value fetched from array
13
23
  def fetch
14
24
  block.present? ? fetch_with_block : fetch_without_block
15
25
  end
@@ -3,73 +3,85 @@
3
3
  module Darthjee
4
4
  module CoreExt
5
5
  module Hash
6
+ # Module holding methods responsible for
7
+ # changing / transforming keys of a Hash
8
+ #
9
+ # @api public
6
10
  module KeyChangeable
7
- def remap_keys(remap)
8
- dup.remap_keys!(remap)
9
- end
10
-
11
- def remap_keys!(keys_map)
12
- KeyChanger.new(self).remap(keys_map)
13
- end
14
-
15
- def lower_camelize_keys(options = {})
16
- dup.lower_camelize_keys!(options)
17
- end
18
-
19
- def lower_camelize_keys!(options = {})
20
- options = options.merge(uppercase_first_letter: false)
21
-
22
- camelize_keys!(options)
23
- end
24
-
25
- def camelize_keys(options = {})
26
- dup.camelize_keys!(options)
27
- end
28
-
29
- def camelize_keys!(options = {})
30
- Hash::KeyChanger.new(self).camelize_keys(options)
11
+ # Change all keys by publically sending methods to the keys without
12
+ # changing the original hash
13
+ #
14
+ # @return [::Hash] New hash with the resulting keys
15
+ # @param [::Array<Symbol>] calls methods to be called form the key`
16
+ #
17
+ # @see #change_keys
18
+ #
19
+ # @example
20
+ # hash = { first: 1, second: 2 }
21
+ # resut = hash.chain_change_keys(:to_s, :size, :to_s, :to_sym)
22
+ # result # returns { :'5' => 1, :'6' => 2 }
23
+ def chain_change_keys(*calls)
24
+ deep_dup.chain_change_keys!(*calls)
31
25
  end
32
26
 
33
- def underscore_keys(options = {})
34
- dup.underscore_keys!(options)
35
- end
27
+ # Change all keys by publically sending methods to the keys
28
+ # changing the original hash
29
+ #
30
+ # @return [::Hash] New hash with the resulting keys
31
+ # @param [::Array<Symbol>] calls methods to be called form the key`
32
+ #
33
+ # @see #chain_change_keys
34
+ #
35
+ # @example (see #chain_change_keys)
36
+ def chain_change_keys!(*calls)
37
+ options = calls.extract_options!
36
38
 
37
- def underscore_keys!(options = {})
38
- Hash::KeyChanger.new(self).underscore_keys(options)
39
+ calls.inject(self) do |h, m|
40
+ h.change_keys!(options, &m)
41
+ end
39
42
  end
40
43
 
41
- # change all keys returning the new map
42
- # options: { recursive: true }
43
- # ex: { "a" =>1 }.change_keys{ |key| key.upcase } == { "A" => 1 }
44
+ # Change all keys returning the new hash
45
+ #
46
+ # @return new Hash with modified keys
47
+ # @param [::Hash] options options to passed to KeyChanger
48
+ # @option options [Boolean] recursive: flag defining the
49
+ # change to happen also
50
+ # on inner hashes (defaults to: true)
51
+ #
52
+ # @see Hash::KeyChanger#change_keys
53
+ #
54
+ # @example
55
+ # hash = { '1' => 1, '2' => { '3' => 2} }
56
+ #
57
+ # result = hash.change_keys do |k|
58
+ # (k.to_i + 1).to_s.to_sym
59
+ # end
60
+ # result # returns { :'2' => 1, :'3' => { :'4' => 2 } }
61
+ #
62
+ # result = hash.change_keys(recursive:false) do |k|
63
+ # (k.to_i + 1).to_s.to_sym
64
+ # end
65
+ # result # returns { :'2' => 1, :'3' => { '3' => 2 } }
44
66
  def change_keys(options = {}, &block)
45
67
  deep_dup.change_keys!(options, &block)
46
68
  end
47
69
 
48
- # change all keys returning the new map
49
- # options: { recursive: true }
50
- # ex: { "a":1 }.change_keys{ |key| key.upcase } == { "A":1 }
70
+ # Change all keys modifying and returning the hash
71
+ #
72
+ # @return self
73
+ # @param [::Hash] options options to passed to KeyChanger
74
+ # @option options [Boolean] recursive: flag defining the
75
+ # change to happen also
76
+ # on inner hashes (defaults to: true)
77
+ #
78
+ # @see Hash::KeyChanger#change_keys
79
+ #
80
+ # @example (see #change_keys)
51
81
  def change_keys!(options = {}, &block)
52
82
  Hash::KeyChanger.new(self).change_keys(options, &block)
53
83
  end
54
84
 
55
- # change all publicaly sending method calls
56
- # options: { recursive: true }
57
- # ex: { a: 1 }.chain_change_keys(:to_s, :upcase) == { "A" =>1 }
58
- def chain_change_keys(*calls)
59
- deep_dup.chain_change_keys!(*calls)
60
- end
61
-
62
- # change all publicaly sending method calls
63
- # options: { recursive: true }
64
- # ex: { a: 1 }.chain_change_keys(:to_s, :upcase) == { "A" =>1 }
65
- def chain_change_keys!(*calls)
66
- options = calls.extract_options!
67
-
68
- calls.inject(self) do |h, m|
69
- h.change_keys!(options, &m)
70
- end
71
- end
72
-
73
85
  # prepend a string to all keys
74
86
  # options {
75
87
  # recursive: true,
@@ -125,6 +137,26 @@ module Darthjee
125
137
  Hash::ValueChanger.new(options, &block).change(self)
126
138
  end
127
139
 
140
+ # Changes the key of the hash without changing it
141
+ #
142
+ # @return [::Hash] new hash
143
+ #
144
+ # @example
145
+ # hash = { a: 1, b: 2 }
146
+ # hash.remap_keys(a: :b, b: :c) # returns { b: 1, c: 2 }
147
+ def remap_keys(remap)
148
+ dup.remap_keys!(remap)
149
+ end
150
+
151
+ # Changes the key of the hash changing the original
152
+ #
153
+ # @return [::Hash] self
154
+ #
155
+ # @example (see #remap_keys)
156
+ def remap_keys!(keys_map)
157
+ KeyChanger.new(self).remap(keys_map)
158
+ end
159
+
128
160
  private
129
161
 
130
162
  # changes the text of the keys
@@ -3,6 +3,7 @@
3
3
  module Darthjee
4
4
  module CoreExt
5
5
  module Hash
6
+ # @api private
6
7
  class KeyChanger
7
8
  def initialize(hash)
8
9
  @hash = hash
@@ -16,10 +17,20 @@ module Darthjee
16
17
  hash.merge! new_hash
17
18
  end
18
19
 
19
- def change_keys(settings = {}, &block)
20
- merge_options({
21
- recursive: true
22
- }, settings)
20
+ # Change the keys of the given hash returning the new hash
21
+ #
22
+ # @return New hash after keys tranformation
23
+ #
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)
28
+ #
29
+ # @example (see Hash#change_keys)
30
+ def change_keys(options = {}, &block)
31
+ options = {
32
+ recursive: true
33
+ }.merge!(options)
23
34
 
24
35
  if options[:recursive]
25
36
  hash.deep_transform_keys!(&block)
@@ -28,31 +39,37 @@ module Darthjee
28
39
  end
29
40
  end
30
41
 
31
- def camelize_keys(settings = {})
32
- merge_options({
33
- uppercase_first_letter: true
34
- }, settings)
42
+ # Performs camelization of the keys of the hash
43
+ #
44
+ # @return [::Hash] the given hash with it's keys changed
45
+ # @param [::Hash] options options
46
+ # @option options [::Boolean] uppercase_first_letter: flag
47
+ # defining the type of CamelCase
48
+ #
49
+ # @example (see Hash#camelize_keys)
50
+ def camelize_keys(options = {})
51
+ options = {
52
+ uppercase_first_letter: true
53
+ }.merge!(options)
35
54
 
36
55
  type = options[:uppercase_first_letter] ? :upper : :lower
37
56
 
38
- change_keys do |k|
57
+ change_keys(options) do |k|
39
58
  k.camelize(type)
40
59
  end
41
60
  end
42
61
 
43
- def underscore_keys(settings = {})
44
- merge_options({}, settings)
45
-
46
- change_keys(&:underscore)
62
+ def underscore_keys(options = {})
63
+ change_keys(options, &:underscore)
47
64
  end
48
65
 
49
66
  def change_text(options = {})
50
- merge_options({
51
- type: :keep
52
- }, options)
67
+ options = {
68
+ type: :keep
69
+ }.merge!(options)
53
70
 
54
- change_keys do |key|
55
- cast_new_key yield(key), key.class
71
+ change_keys(options) do |key|
72
+ cast_new_key yield(key), key.class, options
56
73
  end
57
74
  end
58
75
 
@@ -60,16 +77,8 @@ module Darthjee
60
77
 
61
78
  attr_reader :hash
62
79
 
63
- def merge_options(default, custom)
64
- @options = {}.merge!(default).merge!(custom).merge!(options)
65
- end
66
-
67
- def options
68
- @options ||= {}
69
- end
70
-
71
- def cast_new_key(key, old_clazz)
72
- case class_cast(old_clazz)
80
+ def cast_new_key(key, old_clazz, options)
81
+ case class_cast(old_clazz, options)
73
82
  when :symbol then
74
83
  key.to_sym
75
84
  when :string then
@@ -77,12 +86,13 @@ module Darthjee
77
86
  end
78
87
  end
79
88
 
80
- def keep_class?
89
+ def keep_class?(options)
81
90
  options[:type] == :keep
82
91
  end
83
92
 
84
- def class_cast(old_clazz)
85
- keep_class? && old_clazz.to_s.downcase.to_sym || options[:type]
93
+ def class_cast(old_clazz, options)
94
+ klass = keep_class?(options) && old_clazz.to_s.downcase.to_sym
95
+ klass || options[:type]
86
96
  end
87
97
  end
88
98
  end
@@ -3,37 +3,136 @@
3
3
  module Darthjee
4
4
  module CoreExt
5
5
  module Hash
6
+ # Class responsible for changing values on a hash
7
+ #
8
+ # @attribute [Boolean] recursive
9
+ # flag telling to apply transformation recursively
10
+ # @attribute [Boolean] skip_inner
11
+ # flag telling to not apply change block call to inner hashes
12
+ # @attribute [::Proc] block
13
+ # block to be called when changing the values
14
+ #
15
+ # @example
16
+ # (see initialize)
17
+ #
18
+ # @example
19
+ # (see #change)
6
20
  class ValueChanger
7
- attr_accessor :options, :block
21
+ attr_accessor :recursive, :skip_inner, :block
8
22
 
9
- def initialize(options, &block)
10
- @options = {
11
- recursive: true,
12
- skip_inner: true
13
- }.merge(options)
23
+ # @param [Boolean] recursive
24
+ # flag telling to apply transformation recursively
25
+ # @param [Boolean] skip_inner
26
+ # flag telling to not apply change block call to inner hashes
27
+ # @param [::Proc] block
28
+ # block to be called when changing the values
29
+ #
30
+ #
31
+ # @example
32
+ # changer = Darthjee::CoreExt::Hash::ValueChanger.new(
33
+ # recursive: false,
34
+ # skip_inner: false,
35
+ # &:class
36
+ # )
37
+ #
38
+ # hash = { a: 1, b: { c: 2 }, d: [{ e: 1 }] }
39
+ # changer.change(hash) # {
40
+ # # a: Integer,
41
+ # # b: Hash,
42
+ # # d: Array
43
+ # # }
44
+ def initialize(recursive: true, skip_inner: true, &block)
45
+ @recursive = recursive
46
+ @skip_inner = skip_inner
14
47
 
15
48
  @block = block
16
49
  end
17
50
 
51
+ # Change the given object
52
+ #
53
+ # @return the resulting object (hash or array)
54
+ # with it`s values changed
55
+ # @param [::Hash/::Array] object
56
+ # object to have it's values changed
57
+ #
58
+ # @example
59
+ # changer = Darthjee::CoreExt::Hash::ValueChanger.new do |value|
60
+ # value.to_s.size
61
+ # end
62
+ #
63
+ # hash = { a: 15, b: { c: 2 }, d: [{ e: 100 }] }
64
+ # changer.change(hash) # {
65
+ # # a: 2,
66
+ # # b: { c: 1 },
67
+ # # d: [{ e: 3 }]
68
+ # # }
69
+ #
70
+ # @example
71
+ # changer = Darthjee::CoreExt::Hash::ValueChanger.new(
72
+ # skip_inner: true
73
+ # ) do |value|
74
+ # value.to_s.size
75
+ # end
76
+ #
77
+ # hash = { a: 15, b: { c: 2 }, d: [{ e: 100 }] }
78
+ # changer.change(hash) # {
79
+ # # a: 2,
80
+ # # b: 11,
81
+ # # d: 7
82
+ # # }
83
+ #
84
+ # @example
85
+ # changer = Darthjee::CoreExt::Hash::ValueChanger.new(
86
+ # recursive: true
87
+ # ) do |value|
88
+ # value.to_s.size
89
+ # end
90
+ #
91
+ # hash = { a: 15, b: { c: 2 }, d: [{ e: 100 }] }
92
+ # changer.change(hash) # {
93
+ # # a: 2,
94
+ # # b: { c: 1 },
95
+ # # d: [{ e: 3 }]
96
+ # # }
97
+ #
98
+ # @example
99
+ # changer = Darthjee::CoreExt::Hash::ValueChanger.new do |value|
100
+ # value.to_s.size
101
+ # end
102
+ #
103
+ # array = [15, { c: 2 }, [{ e: 100 }]]
104
+ #
105
+ # changer.change(array) # [
106
+ # # 2,
107
+ # # { c: 1 },
108
+ # # [{ e: 3 }]
109
+ # # ]
18
110
  def change(object)
19
111
  if object.respond_to?(:change_values)
20
112
  change_hash(object)
21
113
  elsif iterable?(object)
22
114
  change_array(object)
115
+ else
116
+ object
23
117
  end
24
118
  end
25
119
 
26
120
  private
27
121
 
122
+ # Apply change logic to hash object
123
+ #
124
+ # @private
28
125
  def change_hash(original_hash)
29
126
  original_hash.tap do |hash|
30
127
  original_hash.each do |key, value|
31
- value = new_value(value)
32
- hash[key] = value
128
+ hash[key] = new_value(value)
33
129
  end
34
130
  end
35
131
  end
36
132
 
133
+ # Apply change logic to iterator
134
+ #
135
+ # @private
37
136
  def change_array(array)
38
137
  method = %w[map! map].find { |m| array.respond_to? m }
39
138
 
@@ -48,8 +147,16 @@ module Darthjee
48
147
  end
49
148
  end
50
149
 
150
+ # check wehether block should be called over
151
+ # value or not
152
+ #
153
+ # when the block is not iterable (not Array or Hash)
154
+ # or when skip_inner option is set to be false,
155
+ # then block should be called
156
+ #
157
+ # @private
51
158
  def change_value?(value)
52
- !iterable?(value) || !options[:skip_inner]
159
+ !iterable?(value) || !skip_inner
53
160
  end
54
161
 
55
162
  def iterable?(value)
@@ -58,11 +165,21 @@ module Darthjee
58
165
 
59
166
  def new_value(value)
60
167
  value = block.call(value) if change_value?(value)
61
- apply_recursion?(value) ? change(value) : value
168
+
169
+ return value unless apply_recursion?(value)
170
+
171
+ change(value)
62
172
  end
63
173
 
64
174
  def apply_recursion?(value)
65
- iterable?(value) && options[:recursive]
175
+ iterable?(value) && recursive
176
+ end
177
+
178
+ def options
179
+ @options ||= {
180
+ recursive: recursive,
181
+ skip_inner: skip_inner
182
+ }
66
183
  end
67
184
  end
68
185
  end