darthjee-core_ext 1.7.3 → 1.7.4

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