darthjee-core_ext 1.5.6 → 1.6.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 (68) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +14 -0
  3. data/.rubocop.yml +17 -0
  4. data/.rubocop_todo.yml +12 -0
  5. data/Gemfile +2 -1
  6. data/Rakefile +2 -0
  7. data/core_ext.gemspec +6 -3
  8. data/lib/darthjee/core_ext/array/hash_builder.rb +21 -13
  9. data/lib/darthjee/core_ext/array.rb +4 -2
  10. data/lib/darthjee/core_ext/date.rb +2 -0
  11. data/lib/darthjee/core_ext/enumerable.rb +5 -3
  12. data/lib/darthjee/core_ext/hash/chain_fetcher.rb +33 -0
  13. data/lib/darthjee/core_ext/hash/deep_hash_constructor.rb +62 -60
  14. data/lib/darthjee/core_ext/hash/key_changer.rb +64 -54
  15. data/lib/darthjee/core_ext/hash/keys_sorter.rb +31 -0
  16. data/lib/darthjee/core_ext/hash/squasher.rb +31 -0
  17. data/lib/darthjee/core_ext/hash/to_hash_mapper.rb +21 -0
  18. data/lib/darthjee/core_ext/hash/value_changer.rb +48 -44
  19. data/lib/darthjee/core_ext/hash.rb +28 -58
  20. data/lib/darthjee/core_ext/math.rb +4 -2
  21. data/lib/darthjee/core_ext/numeric.rb +5 -3
  22. data/lib/darthjee/core_ext/object/default_value.rb +2 -1
  23. data/lib/darthjee/core_ext/object.rb +2 -0
  24. data/lib/darthjee/core_ext/symbol.rb +2 -0
  25. data/lib/darthjee/core_ext/time.rb +2 -0
  26. data/lib/darthjee/core_ext/version.rb +3 -1
  27. data/lib/darthjee/core_ext.rb +2 -0
  28. data/lib/darthjee.rb +2 -1
  29. data/spec/lib/array_spec.rb +27 -19
  30. data/spec/lib/date_spec.rb +2 -0
  31. data/spec/lib/enumerable_spec.rb +10 -8
  32. data/spec/lib/hash/chain_fetcher_spec.rb +11 -0
  33. data/spec/lib/hash/deep_hash_constructor_spec.rb +3 -1
  34. data/spec/lib/hash/key_changer_spec.rb +19 -5
  35. data/spec/lib/hash/keys_sorter_spec.rb +10 -0
  36. data/spec/lib/hash/squasher_spec.rb +9 -0
  37. data/spec/lib/hash/to_hash_mapper_spec.rb +10 -0
  38. data/spec/lib/hash_spec.rb +16 -46
  39. data/spec/lib/math_spec.rb +2 -0
  40. data/spec/lib/numeric_spec.rb +2 -0
  41. data/spec/lib/object/default_value_spe.rb +2 -0
  42. data/spec/lib/object_spec.rb +2 -0
  43. data/spec/lib/symbol_spec.rb +2 -0
  44. data/spec/lib/time_spec.rb +2 -0
  45. data/spec/spec_helper.rb +2 -1
  46. data/spec/support/models/default_value.rb +2 -0
  47. data/spec/support/models/hash/value_changer/dummy.rb +19 -13
  48. data/spec/support/models/hash/value_changer/dummy_iteractor.rb +13 -8
  49. data/spec/support/shared_examples/{array_random.rb → array/array_random.rb} +5 -2
  50. data/spec/support/shared_examples/clean.rb +14 -2
  51. data/spec/support/shared_examples/date.rb +2 -0
  52. data/spec/support/shared_examples/expected.rb +2 -1
  53. data/spec/support/shared_examples/{chain_fetch.rb → hash/chain_fetch.rb} +9 -7
  54. data/spec/support/shared_examples/{chain_hash_keys_changer.rb → hash/chain_hash_keys_changer.rb} +14 -11
  55. data/spec/support/shared_examples/{hash_keys_changer.rb → hash/hash_keys_changer.rb} +7 -5
  56. data/spec/support/shared_examples/hash/hash_squasher.rb +23 -0
  57. data/spec/support/shared_examples/{hash_transpose.rb → hash/hash_transpose.rb} +8 -6
  58. data/spec/support/shared_examples/hash/keys_appender.rb +69 -0
  59. data/spec/support/shared_examples/{keys_camelizer.rb → hash/keys_camelizer.rb} +6 -4
  60. data/spec/support/shared_examples/hash/keys_sorter.rb +67 -0
  61. data/spec/support/shared_examples/{keys_underscorer.rb → hash/keys_underscorer.rb} +4 -3
  62. data/spec/support/shared_examples/{map_to_hash.rb → hash/map_to_hash.rb} +16 -16
  63. data/spec/support/shared_examples/{remap.rb → hash/remap.rb} +16 -13
  64. data/spec/support/shared_examples/hash/value_changer.rb +192 -0
  65. metadata +76 -30
  66. data/circle.yml +0 -10
  67. data/spec/support/shared_examples/keys_appender.rb +0 -43
  68. data/spec/support/shared_examples/value_changer.rb +0 -147
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2d4baa96e398c438d33f1897569c232d4bdb7b9b
4
- data.tar.gz: c1b50dee152a7c8e7c09767a2725b5687729d119
3
+ metadata.gz: f91f602918068826bc0e97f7e555f680226b429c
4
+ data.tar.gz: ccb555082fd2cc831024d1f9b565f6ca2dcf543a
5
5
  SHA512:
6
- metadata.gz: 6ed4bfbbefa59ff507eaf7c7181059d7e5b278db940a98ba8dac2049be91d1500315812a3459cbd5e6cdfae97024428dd6089899d16128e1b410c90f7fe80646
7
- data.tar.gz: 4a4f5bb5b2cea7b7e1be4a64e897af6659586eca6f464d6126f4e16861a91d9a229957bfe56e2beebf5a5e44b6e5b8815bc749e3ea7087e03c1f0d3c1ed34376
6
+ metadata.gz: 11af6fe53de559202c101a5809ccbeca632c8daaba4a49d8a7415a75885f697d378bbd970607ee89f5d26ec145d1309875b0f20d2fa2abbca2f7ba55eadcbe01
7
+ data.tar.gz: 874149c8200c544b455efce3302aba8a720794272457b72dcb0353d9d05df68441a26753f9a368a082d92a1cf23947791894aee76aba280c039eb3159805d2f5
@@ -0,0 +1,14 @@
1
+ version: 2
2
+ jobs:
3
+ build:
4
+ docker:
5
+ - image: circleci/ruby:2.4.1
6
+ steps:
7
+ - checkout
8
+ - run: curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
9
+ - run: chmod +x ./cc-test-reporter
10
+ - run: ./cc-test-reporter before-build
11
+ - run: bundle install
12
+ - run: bundle exec rspec
13
+ - run: rubocop
14
+ - run: ./cc-test-reporter after-build --exit-code $?
data/.rubocop.yml ADDED
@@ -0,0 +1,17 @@
1
+ inherit_from: .rubocop_todo.yml
2
+
3
+ AllCops:
4
+ TargetRubyVersion: 2.4
5
+
6
+ Naming/PredicateName:
7
+ Exclude:
8
+ - 'lib/darthjee/core_ext/object.rb'
9
+
10
+ Metrics/ClassLength:
11
+ Exclude:
12
+ - 'lib/darthjee/core_ext/hash.rb'
13
+
14
+ Metrics/BlockLength:
15
+ Exclude:
16
+ - 'spec/**/*_spec.rb'
17
+ - 'spec/support/shared_*/**/*.rb'
data/.rubocop_todo.yml ADDED
@@ -0,0 +1,12 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2018-07-26 20:39:06 +0000 using RuboCop version 0.58.1.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Offense count: 16
10
+ Style/Documentation:
11
+ Enabled: false
12
+
data/Gemfile CHANGED
@@ -1,5 +1,6 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  # Specify your gem's dependencies in credential_builder.gemspec
4
6
  gemspec
5
-
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'bundler/gem_tasks'
2
4
  require 'rspec/core/rake_task'
3
5
 
data/core_ext.gemspec CHANGED
@@ -1,5 +1,6 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
5
  require 'darthjee/core_ext/version'
5
6
 
@@ -20,8 +21,10 @@ Gem::Specification.new do |gem|
20
21
  gem.add_runtime_dependency 'activesupport', '>= 5.x'
21
22
 
22
23
  gem.add_development_dependency 'bundler', '~> 1.6'
24
+ gem.add_development_dependency 'pry-nav', '~> 0.2.4'
23
25
  gem.add_development_dependency 'rake', '>= 12.3.1'
24
26
  gem.add_development_dependency 'rspec', '>= 3.7'
25
- gem.add_development_dependency 'pry-nav', '~> 0.2.4'
27
+ gem.add_development_dependency 'rubocop'
26
28
  gem.add_development_dependency 'simplecov', '~> 0.14.1'
29
+ gem.add_development_dependency 'yard'
27
30
  end
@@ -1,20 +1,28 @@
1
- class Array::HashBuilder
2
- attr_accessor :values, :keys
1
+ # frozen_string_literal: true
3
2
 
4
- def initialize(values, keys)
5
- @values = values.dup
6
- @keys = keys.dup
7
- end
3
+ class Array
4
+ class HashBuilder
5
+ attr_accessor :values, :keys
8
6
 
9
- def build
10
- fixes_sizes
7
+ def initialize(values, keys)
8
+ @values = values.dup
9
+ @keys = keys.dup
10
+ end
11
11
 
12
- Hash[[keys, values].transpose]
13
- end
12
+ def build
13
+ fixes_sizes
14
+
15
+ Hash[[keys, values].transpose]
16
+ end
17
+
18
+ private
14
19
 
15
- private
20
+ def fixes_sizes
21
+ values.concat Array.new(keys.size - values.size) if needs_resizing?
22
+ end
16
23
 
17
- def fixes_sizes
18
- values.concat Array.new(keys.size - values.size) if keys.size > values.size
24
+ def needs_resizing?
25
+ keys.size > values.size
26
+ end
19
27
  end
20
28
  end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Array
2
- autoload :HashBuilder, 'darthjee/core_ext/array/hash_builder'
4
+ autoload :HashBuilder, 'darthjee/core_ext/array/hash_builder'
3
5
 
4
6
  def mapk(*keys)
5
7
  keys.inject(self) do |enum, key|
@@ -39,6 +41,6 @@ class Array
39
41
  end
40
42
 
41
43
  def random!
42
- self.slice!(rand(size))
44
+ slice!(rand(size))
43
45
  end
44
46
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Date
2
4
  def days_between(other_date)
3
5
  (self - other_date.to_date).abs
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Enumerable
2
4
  def clean
3
5
  deep_dup.clean!
@@ -38,8 +40,8 @@ module Enumerable
38
40
 
39
41
  private
40
42
 
41
- def empty_value?(v)
42
- v.nil? || v.try(:empty?) ||
43
- ((v.is_a?(Hash) || v.is_a?(Array)) && v.clean!.empty?)
43
+ def empty_value?(value)
44
+ value.nil? || value.try(:empty?) ||
45
+ ((value.is_a?(Hash) || value.is_a?(Array)) && value.clean!.empty?)
44
46
  end
45
47
  end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Hash
4
+ class ChainFetcher
5
+ def initialize(hash, *keys, &block)
6
+ @hash = hash
7
+ @keys = keys
8
+ @block = block
9
+ end
10
+
11
+ def fetch
12
+ block.present? ? fetch_with_block : fetch_without_block
13
+ end
14
+
15
+ private
16
+
17
+ attr_reader :hash, :keys, :block
18
+
19
+ def fetch_with_block
20
+ @hash = hash.fetch(keys.shift) do |*args|
21
+ missed_keys = keys
22
+ @keys = []
23
+ block.call(*(args + [missed_keys]))
24
+ end until keys.empty?
25
+ hash
26
+ end
27
+
28
+ def fetch_without_block
29
+ @hash = hash.fetch(keys.shift) until keys.empty?
30
+ hash
31
+ end
32
+ end
33
+ end
@@ -1,83 +1,85 @@
1
- class Hash::DeepHashConstructor
2
- attr_accessor :separator
1
+ # frozen_string_literal: true
3
2
 
4
- def initialize(separator)
5
- @separator = separator
6
- end
3
+ class Hash
4
+ class DeepHashConstructor
5
+ attr_accessor :separator
7
6
 
8
- def deep_hash(object)
9
- if object.is_a? Array
10
- array_deep_hash(object)
11
- elsif object.is_a? Hash
12
- hash_deep_hash(object)
13
- else
14
- object
7
+ def initialize(separator)
8
+ @separator = separator
15
9
  end
16
- end
17
10
 
18
- private
11
+ def deep_hash(object)
12
+ if object.is_a? Array
13
+ array_deep_hash(object)
14
+ elsif object.is_a? Hash
15
+ hash_deep_hash(object)
16
+ else
17
+ object
18
+ end
19
+ end
19
20
 
20
- def array_deep_hash(array)
21
- array.map { |v| v.is_a?(Hash) ? deep_hash(v) : v }
22
- end
21
+ private
23
22
 
24
- def hash_deep_hash(hash)
25
- {}.tap do |new_hash|
26
- hash.each do |k, v|
27
- base_key, child_key = split_key(k, separator)
28
- set_deep_hash_positioned_value(new_hash, base_key, v, child_key)
29
- end
23
+ def array_deep_hash(array)
24
+ array.map { |v| v.is_a?(Hash) ? deep_hash(v) : v }
25
+ end
30
26
 
31
- new_hash.each do |k, v|
32
- new_hash[k] = deep_hash(v)
27
+ def hash_deep_hash(hash)
28
+ {}.tap do |new_hash|
29
+ hash.each do |k, v|
30
+ base_key, child_key = split_key(k, separator)
31
+ set_deep_hash_positioned_value(new_hash, base_key, v, child_key)
32
+ end
33
+
34
+ new_hash.each do |k, v|
35
+ new_hash[k] = deep_hash(v)
36
+ end
33
37
  end
34
38
  end
35
- end
36
39
 
37
- def split_key(key, separator)
38
- separator_rxp = (separator == '.') ? "\\#{separator}" : separator
39
- skipper = "[^#{separator}]"
40
- regexp = Regexp.new("^(#{skipper}*)#{separator_rxp}(.*)")
41
- match = key.match(regexp)
40
+ def split_key(key, separator)
41
+ separator_rxp = separator == '.' ? "\\#{separator}" : separator
42
+ skipper = "[^#{separator}]"
43
+ regexp = Regexp.new("^(#{skipper}*)#{separator_rxp}(.*)")
44
+ match = key.match(regexp)
42
45
 
43
- match ? match[1..2] : key
44
- end
46
+ match ? match[1..2] : key
47
+ end
45
48
 
46
- def set_deep_hash_array_value(hash, base_key, index, value, key = nil)
47
- key_without_index = base_key.gsub("[#{index}]", '')
48
- hash[key_without_index] ||= []
49
+ def set_deep_hash_array_value(hash, base_key, index, value, key = nil)
50
+ key_without_index = base_key.gsub("[#{index}]", '')
51
+ hash[key_without_index] ||= []
49
52
 
50
- if key.nil?
51
- hash[key_without_index][index] = value
52
- else
53
- hash[key_without_index][index] ||= {}
54
- hash[key_without_index][index][key] = value
53
+ if key.nil?
54
+ hash[key_without_index][index] = value
55
+ else
56
+ hash[key_without_index][index] ||= {}
57
+ hash[key_without_index][index][key] = value
58
+ end
55
59
  end
56
- end
57
60
 
58
- def set_deep_hash_positioned_value(new_hash, base_key, v, child_key)
59
- index = array_index(base_key)
61
+ def set_deep_hash_positioned_value(new_hash, base_key, value, child_key)
62
+ index = array_index(base_key)
60
63
 
61
- if index
62
- set_deep_hash_array_value(new_hash, base_key, index, v, child_key)
63
- else
64
- set_deep_hash_value(new_hash, base_key, v, child_key)
64
+ if index
65
+ set_deep_hash_array_value(new_hash, base_key, index, value, child_key)
66
+ else
67
+ set_deep_hash_value(new_hash, base_key, value, child_key)
68
+ end
65
69
  end
66
- end
67
70
 
68
- def array_index(key)
69
- match = key.match(/\[([^)]+)\]/)
70
- if match
71
- match[1].to_i
71
+ def array_index(key)
72
+ match = key.match(/\[([^)]+)\]/)
73
+ match && match[1].to_i
72
74
  end
73
- end
74
75
 
75
- def set_deep_hash_value(hash, base_key, value, key = nil)
76
- if key.nil?
77
- hash[base_key] = value
78
- else
79
- hash[base_key] ||= {}
80
- hash[base_key][key] = value
76
+ def set_deep_hash_value(hash, base_key, value, key = nil)
77
+ if key.nil?
78
+ hash[base_key] = value
79
+ else
80
+ hash[base_key] ||= {}
81
+ hash[base_key][key] = value
82
+ end
81
83
  end
82
84
  end
83
85
  end
@@ -1,76 +1,86 @@
1
- class Hash::KeyChanger
2
- attr_reader :hash, :block
1
+ # frozen_string_literal: true
3
2
 
4
- def initialize(hash)
5
- @hash = hash
6
- end
3
+ class Hash
4
+ class KeyChanger
5
+ def initialize(hash)
6
+ @hash = hash
7
+ end
7
8
 
8
- def change_keys(settings = {}, &block)
9
- merge_options({
10
- recursive: true
11
- }, settings)
9
+ def remap(keys_map)
10
+ new_hash = {}
11
+ keys_map.each do |o, n|
12
+ new_hash[n] = hash.delete(o)
13
+ end
14
+ hash.merge! new_hash
15
+ end
12
16
 
13
- if options[:recursive]
14
- hash.deep_transform_keys!(&block)
15
- else
16
- hash.transform_keys!(&block)
17
+ def change_keys(settings = {}, &block)
18
+ merge_options({
19
+ recursive: true
20
+ }, settings)
21
+
22
+ if options[:recursive]
23
+ hash.deep_transform_keys!(&block)
24
+ else
25
+ hash.transform_keys!(&block)
26
+ end
17
27
  end
18
- end
19
28
 
20
- def camelize_keys(settings = {})
21
- merge_options({
22
- uppercase_first_letter: true
23
- }, settings)
29
+ def camelize_keys(settings = {})
30
+ merge_options({
31
+ uppercase_first_letter: true
32
+ }, settings)
24
33
 
25
- type = options[:uppercase_first_letter] ? :upper : :lower
34
+ type = options[:uppercase_first_letter] ? :upper : :lower
26
35
 
27
- change_keys do |k|
28
- k.camelize(type)
36
+ change_keys do |k|
37
+ k.camelize(type)
38
+ end
29
39
  end
30
- end
31
40
 
32
- def underscore_keys(settings = {})
33
- merge_options({}, settings)
41
+ def underscore_keys(settings = {})
42
+ merge_options({}, settings)
34
43
 
35
- change_keys do |k|
36
- k.underscore
44
+ change_keys(&:underscore)
37
45
  end
38
- end
39
46
 
40
- def change_text(options = {}, &block)
41
- merge_options({
42
- type: :keep
43
- }, options)
47
+ def change_text(options = {})
48
+ merge_options({
49
+ type: :keep
50
+ }, options)
44
51
 
45
- change_keys do |key|
46
- cast_new_key block.call(key), key.class
52
+ change_keys do |key|
53
+ cast_new_key yield(key), key.class
54
+ end
47
55
  end
48
- end
49
56
 
50
- private
57
+ private
51
58
 
52
- def merge_options(default, custom)
53
- @options = {}.merge!(default).merge!(custom).merge!(options)
54
- end
59
+ attr_reader :hash
55
60
 
56
- def options
57
- @options ||= {}
58
- end
61
+ def merge_options(default, custom)
62
+ @options = {}.merge!(default).merge!(custom).merge!(options)
63
+ end
59
64
 
60
- def cast_new_key(key, old_clazz)
61
- case class_cast(old_clazz)
62
- when :symbol then
63
- key.to_sym
64
- when :string then
65
- key.to_s
65
+ def options
66
+ @options ||= {}
66
67
  end
67
- end
68
68
 
69
- def keep_class?
70
- options[:type] == :keep
71
- end
69
+ def cast_new_key(key, old_clazz)
70
+ case class_cast(old_clazz)
71
+ when :symbol then
72
+ key.to_sym
73
+ when :string then
74
+ key.to_s
75
+ end
76
+ end
77
+
78
+ def keep_class?
79
+ options[:type] == :keep
80
+ end
72
81
 
73
- def class_cast(old_clazz)
74
- keep_class? && old_clazz.to_s.downcase.to_sym || options[:type]
82
+ def class_cast(old_clazz)
83
+ keep_class? && old_clazz.to_s.downcase.to_sym || options[:type]
84
+ end
75
85
  end
76
- end
86
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Hash
4
+ class KeysSorter
5
+ def initialize(hash, recursive: true)
6
+ @hash = hash
7
+ @recursive = recursive
8
+ end
9
+
10
+ def sort
11
+ {}.tap do |new_hash|
12
+ sorted_keys.each do |key|
13
+ new_hash[key] = change_value(hash[key])
14
+ end
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def sorted_keys
21
+ hash.keys.sort
22
+ end
23
+
24
+ def change_value(value)
25
+ return value unless value.is_a?(Hash) && recursive
26
+ value.sort_keys(recursive: true)
27
+ end
28
+
29
+ attr_reader :hash, :recursive
30
+ end
31
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Hash
4
+ module Squasher
5
+ class Builder
6
+ attr_reader :key, :value
7
+
8
+ def initialize(key, value)
9
+ @value = value
10
+ @key = key
11
+ end
12
+
13
+ def to_h
14
+ if value.is_a? Hash
15
+ value.squash.inject({}) do |hash, (k, v)|
16
+ new_key = [key, k].join('.')
17
+ hash.merge!(new_key => v)
18
+ end
19
+ else
20
+ { key => value }
21
+ end
22
+ end
23
+ end
24
+
25
+ def self.squash(origin)
26
+ origin.inject({}) do |hash, (key, value)|
27
+ hash.merge!(Builder.new(key, value).to_h)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Hash
4
+ class ToHashMapper
5
+ def initialize(hash)
6
+ @hash = hash
7
+ end
8
+
9
+ def map
10
+ {}.tap do |new_hash|
11
+ hash.each do |k, v|
12
+ new_hash[k] = yield(k, v)
13
+ end
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ attr_reader :hash
20
+ end
21
+ end