darthjee-core_ext 1.5.6 → 1.6.0

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