darthjee-core_ext 1.7.4 → 2.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 (82) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +7 -1
  3. data/.gitignore +2 -0
  4. data/.reek.yml +3 -0
  5. data/ARRAY_README.md +72 -15
  6. data/CLASS_README.md +154 -0
  7. data/DATE_README.md +19 -9
  8. data/Dockerfile +2 -5
  9. data/ENUMERABLE_README.md +154 -4
  10. data/HASH_README.md +276 -135
  11. data/MATH_README.md +14 -10
  12. data/OBJECT_README.md +18 -35
  13. data/README.md +8 -4
  14. data/Rakefile +1 -0
  15. data/SYMBOL_README.md +13 -18
  16. data/config/rubycritc.rb +12 -0
  17. data/config/yardstick.yml +45 -3
  18. data/core_ext.gemspec +10 -8
  19. data/docker-compose.yml +15 -7
  20. data/lib/darthjee/core_ext/array.rb +17 -12
  21. data/lib/darthjee/core_ext/array/hash_builder.rb +20 -4
  22. data/lib/darthjee/core_ext/class.rb +28 -10
  23. data/lib/darthjee/core_ext/date.rb +1 -0
  24. data/lib/darthjee/core_ext/enumerable.rb +67 -30
  25. data/lib/darthjee/core_ext/hash.rb +4 -2
  26. data/lib/darthjee/core_ext/hash/cameliazable.rb +39 -8
  27. data/lib/darthjee/core_ext/hash/chain_fetcher.rb +17 -1
  28. data/lib/darthjee/core_ext/hash/changeable.rb +88 -0
  29. data/lib/darthjee/core_ext/hash/deep_hash_constructor.rb +127 -63
  30. data/lib/darthjee/core_ext/hash/deep_hash_constructor/setter.rb +112 -0
  31. data/lib/darthjee/core_ext/hash/key_changeable.rb +126 -54
  32. data/lib/darthjee/core_ext/hash/key_changer.rb +140 -40
  33. data/lib/darthjee/core_ext/hash/keys_sorter.rb +42 -6
  34. data/lib/darthjee/core_ext/hash/squasher.rb +131 -18
  35. data/lib/darthjee/core_ext/hash/transformable.rb +133 -41
  36. data/lib/darthjee/core_ext/hash/transposeable.rb +37 -8
  37. data/lib/darthjee/core_ext/hash/value_changer.rb +76 -36
  38. data/lib/darthjee/core_ext/math.rb +37 -6
  39. data/lib/darthjee/core_ext/numeric.rb +10 -0
  40. data/lib/darthjee/core_ext/object.rb +29 -0
  41. data/lib/darthjee/core_ext/symbol.rb +22 -2
  42. data/lib/darthjee/core_ext/version.rb +1 -1
  43. data/scripts/check_readme.sh +6 -0
  44. data/scripts/rubycritic.sh +10 -0
  45. data/spec/integration/readme/array_spec.rb +96 -0
  46. data/spec/integration/readme/class_spec.rb +123 -0
  47. data/spec/integration/readme/date_spec.rb +20 -0
  48. data/spec/integration/readme/enumerable_spec.rb +87 -0
  49. data/spec/integration/readme/hash_spec.rb +391 -0
  50. data/spec/integration/readme/math_spec.rb +31 -0
  51. data/spec/integration/readme/object_spec.rb +49 -0
  52. data/spec/integration/readme/symbol_spec.rb +29 -0
  53. data/spec/integration/yard/darthjee/core_ext/enumerable_spec.rb +24 -4
  54. data/spec/integration/yard/darthjee/core_ext/hash/cameliazable_spec.rb +11 -0
  55. data/spec/integration/yard/darthjee/core_ext/hash/changeable_spec.rb +68 -0
  56. data/spec/integration/yard/darthjee/core_ext/hash/deep_hash_constructor/setter_spec.rb +34 -0
  57. data/spec/integration/yard/darthjee/core_ext/hash/deep_hash_constructor_spec.rb +65 -0
  58. data/spec/integration/yard/darthjee/core_ext/hash/key_changeable_spec.rb +8 -0
  59. data/spec/integration/yard/darthjee/core_ext/hash/key_changer_spec.rb +59 -0
  60. data/spec/integration/yard/darthjee/core_ext/hash/keys_sorter_spec.rb +25 -0
  61. data/spec/integration/yard/darthjee/core_ext/hash/squasher_spec.rb +60 -0
  62. data/spec/integration/yard/darthjee/core_ext/hash/transformable_spec.rb +66 -36
  63. data/spec/integration/yard/darthjee/core_ext/hash/transposeable_spec.rb +35 -0
  64. data/spec/integration/yard/darthjee/core_ext/hash_spec.rb +13 -2
  65. data/spec/integration/yard/darthjee/core_ext/math_spec.rb +28 -0
  66. data/spec/integration/yard/darthjee/core_ext/numeric_spec.rb +11 -0
  67. data/spec/integration/yard/darthjee/core_ext/object_spec.rb +47 -0
  68. data/spec/integration/yard/darthjee/core_ext/symbol_spec.rb +17 -0
  69. data/spec/lib/darthjee/core_ext/hash/deep_hash_constructor/setter_spec.rb +64 -0
  70. data/spec/lib/darthjee/core_ext/hash/deep_hash_constructor_spec.rb +16 -156
  71. data/spec/lib/darthjee/core_ext/hash/keys_sorter_spec.rb +5 -4
  72. data/spec/lib/darthjee/core_ext/hash/squasher_spec.rb +8 -2
  73. data/spec/lib/darthjee/core_ext/hash/value_changer_spec.rb +4 -12
  74. data/spec/lib/hash_spec.rb +92 -146
  75. data/spec/lib/object_spec.rb +32 -0
  76. data/spec/support/models/client.rb +22 -0
  77. data/spec/support/shared_examples/hash/deep_hash.rb +166 -0
  78. data/spec/support/shared_examples/hash/hash_squasher.rb +54 -9
  79. data/spec/support/shared_examples/hash/keys_sorter.rb +266 -6
  80. metadata +70 -8
  81. data/lib/darthjee/core_ext/hash/to_hash_mapper.rb +0 -25
  82. data/spec/lib/darthjee/core_ext/hash/to_hash_mapper_spec.rb +0 -11
@@ -1,11 +1,42 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Math
4
- def self.average(values)
5
- values = values.map { |v| [v, 1] }.to_h unless values.is_a?(Hash)
3
+ module Darthjee
4
+ module CoreExt
5
+ # @api public
6
+ module Math
7
+ # Calculates avarage from a series of values
8
+ #
9
+ # @overload average(values)
10
+ # @param values [::Array] list of values
11
+ #
12
+ # @overload average(values)
13
+ # @param values [::Hash] hash of values and its weights
14
+ #
15
+ # @return [::Float]
16
+ #
17
+ # @example Average of array
18
+ # values = [1,2,3,4]
19
+ #
20
+ # Math.average(values) # returns 2.5
21
+ #
22
+ # @example Average of hash
23
+ # values = { 1 => 3, 7 => 1 }
24
+ #
25
+ # Math.average(values) # returns 2.5
26
+ def average(values)
27
+ if values.is_a?(Hash)
28
+ weight_sum = values.values.sum
29
+ values = values.map { |value, weight| value * weight }
30
+ else
31
+ weight_sum = values.length
32
+ end
6
33
 
7
- values.inject(0) do |sum, vals|
8
- sum + vals.inject { |a, b| a * b }
9
- end / values.values.sum.to_f
34
+ values.sum / weight_sum.to_f
35
+ end
36
+ end
10
37
  end
11
38
  end
39
+
40
+ module Math
41
+ extend Darthjee::CoreExt::Math
42
+ end
@@ -2,7 +2,17 @@
2
2
 
3
3
  module Darthjee
4
4
  module CoreExt
5
+ # @api public
5
6
  module Numeric
7
+ # Returns the percentage over total
8
+ #
9
+ # @param total [::Numeric] total over which to calculate
10
+ # the percentage
11
+ #
12
+ # @return [::Float]
13
+ #
14
+ # @example
15
+ # 10.percent_of(30) # returns 33.33333333333333
6
16
  def percent_of(total)
7
17
  return Float::INFINITY if total&.zero?
8
18
  (to_f / total.to_f) * 100.0
@@ -2,12 +2,41 @@
2
2
 
3
3
  module Darthjee
4
4
  module CoreExt
5
+ # @api public
5
6
  module Object
7
+ # Checks if object is any of the given classes
8
+ #
9
+ # @param classes [::Array<::Class>] classes to be checked
10
+ # against
11
+ #
12
+ # @return [::TrueClass,::FalseClass]
13
+ #
14
+ # @example
15
+ # object = [1, 2, 3]
16
+ #
17
+ # object.is_any?(Hash, Class) # false
18
+ # object.is_any?(Hash, Array) # true
19
+ # object.is_any?(Enumerable, Class) # true
6
20
  def is_any?(*classes)
7
21
  classes.any? do |clazz|
8
22
  is_a?(clazz)
9
23
  end
10
24
  end
25
+
26
+ # Checks if object is evaluated to true
27
+ #
28
+ # @return [::TrueClass,::FalseClass]
29
+ #
30
+ # @example
31
+ # nil.trueful? # returns false
32
+ # [].trueful? # returns true
33
+ # {}.trueful? # returns true
34
+ # "".trueful? # returns true
35
+ def trueful?
36
+ # rubocop: disable Style/DoubleNegation
37
+ !!self
38
+ # rubocop: enable Style/DoubleNegation
39
+ end
11
40
  end
12
41
  end
13
42
  end
@@ -2,11 +2,31 @@
2
2
 
3
3
  module Darthjee
4
4
  module CoreExt
5
+ # @api public
6
+ #
7
+ # @author darthjee
5
8
  module Symbol
6
- def camelize(type = :upper)
7
- to_s.camelize(type).to_sym
9
+ # Creates new symbol camelized
10
+ #
11
+ # @param first_letter [::Symbol] type of first letter
12
+ #
13
+ # @return [::Symbol]
14
+ #
15
+ # @example
16
+ # :the_symbol.camelize # returns :TheSymbol
17
+ def camelize(first_letter = :upper)
18
+ to_s.camelize(first_letter).to_sym
8
19
  end
9
20
 
21
+ # The reverse of {#camelize}
22
+ #
23
+ # Makes an underscored, lowercase form from
24
+ # the expression in the Symbol
25
+ #
26
+ # @return [::Symbol]
27
+ #
28
+ # @example
29
+ # :theSymbol.camelize # returns :the_symbol
10
30
  def underscore
11
31
  to_s.underscore.to_sym
12
32
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Darthjee
4
4
  module CoreExt
5
- VERSION = '1.7.4'
5
+ VERSION = '2.0.0'
6
6
  end
7
7
  end
@@ -0,0 +1,6 @@
1
+ #! /bin/bash
2
+
3
+ PROJECT=darthjee/core_ext
4
+ VERSION=$(grep VERSION lib/$PROJECT/version.rb | sed -e "s/.*'\(.*\)'/\1/g")
5
+
6
+ grep https://www.rubydoc.info/gems/darthjee-core_ext/$VERSION README.md
@@ -0,0 +1,10 @@
1
+ #!/bin/bash
2
+
3
+ DIFF_LIST=$(git diff --name-only $CIRCLE_SHA1 $(git merge-base $CIRCLE_SHA1 origin/master) | grep "^lib/")
4
+
5
+ if [ ! -z "$DIFF_LIST" ]; then
6
+ mkdir -p tmp/rubycritic/compare
7
+ bundle exec rubycritic --format console --branch origin/master -t 0 $DIFF_LIST
8
+ else
9
+ echo "No changes detected. Skipping rubycritic..."
10
+ fi
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Array do
4
+ describe 'readme' do
5
+ describe '#as_hash' do
6
+ subject(:array) { [10, 20, 30, 40] }
7
+
8
+ let(:keys) { %i[ten twenty thirty fourty] }
9
+
10
+ it 'pairs keys and values' do
11
+ expect(array.as_hash(keys))
12
+ .to eq(ten: 10, twenty: 20, thirty: 30, fourty: 40)
13
+ end
14
+ end
15
+
16
+ describe '#average' do
17
+ subject(:array) { [1, 2, 3, 4] }
18
+
19
+ it 'calculates the average' do
20
+ expect(array.average).to eq(2.5)
21
+ end
22
+ end
23
+
24
+ describe '#chain_map' do
25
+ subject(:array) { %i[a long_name sym] }
26
+
27
+ it 'maps calling the methods' do
28
+ expect(array.chain_map(:to_s, :size, :to_s))
29
+ .to eq(%w[1 9 3])
30
+ end
31
+
32
+ context 'when giving a block' do
33
+ let(:mapped) do
34
+ array.chain_map(:to_s, :size) { |v| "final: #{v}" }
35
+ end
36
+
37
+ it 'maps calling the methods' do
38
+ expect(mapped)
39
+ .to eq(['final: 1', 'final: 9', 'final: 3'])
40
+ end
41
+ end
42
+ end
43
+
44
+ describe 'mapk' do
45
+ let(:array) do
46
+ [
47
+ { a: { b: 1 }, b: 2 },
48
+ { a: { b: 3 }, b: 4 }
49
+ ]
50
+ end
51
+
52
+ it 'maps fetching keys' do
53
+ expect(array.mapk(:a, :b)).to eq([1, 3])
54
+ end
55
+ end
56
+
57
+ describe '#procedural_join' do
58
+ subject(:array) { [1, 2, -3, -4, 5] }
59
+
60
+ let(:mapper) { proc { |value| value.to_f.to_s } }
61
+ let(:string) do
62
+ array.procedural_join(mapper) do |_previous, nexte|
63
+ nexte.positive? ? ' +' : ' '
64
+ end
65
+ end
66
+
67
+ it 'joins with grace' do
68
+ expect(string).to eq('1.0 +2.0 -3.0 -4.0 +5.0')
69
+ end
70
+ end
71
+
72
+ describe '#random' do
73
+ let(:array) { [10, 20, 30] }
74
+
75
+ it 'returns a random element' do
76
+ expect(array).to include(array.random)
77
+ end
78
+ end
79
+
80
+ describe '#random!' do
81
+ let(:array) { [10, 20, 30] }
82
+
83
+ it 'returns a random element' do
84
+ expect(array.dup).to include(array.random!)
85
+ end
86
+
87
+ it 'removes an element from array' do
88
+ expect { array.random! }.to change(array, :size).by(-1)
89
+ end
90
+
91
+ it 'no longer includes removed element' do
92
+ expect(array).not_to include(array.random!)
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,123 @@
1
+ # frozen_string_literal: false
2
+
3
+ describe Class do
4
+ describe 'readme' do
5
+ let(:instance) { klass.new }
6
+ let(:other) { klass.new }
7
+
8
+ describe '#default_value' do
9
+ let(:klass) do
10
+ Class.new do |clazz|
11
+ clazz.send(:default_value, :name, 'John')
12
+ end
13
+ end
14
+
15
+ it 'adds method with default value' do
16
+ expect(instance.name)
17
+ .to eq('John')
18
+ end
19
+
20
+ it 'returns the same instance' do
21
+ expect(instance.name)
22
+ .to be_equal(other.name)
23
+ end
24
+ end
25
+
26
+ describe '#default_values' do
27
+ let(:klass) do
28
+ Class.new do |clazz|
29
+ clazz.send(
30
+ :default_values, :name, :nick_name, 'John'
31
+ )
32
+ end
33
+ end
34
+
35
+ it 'adds methods with default value' do
36
+ expect(instance.name)
37
+ .to eq('John')
38
+ end
39
+
40
+ it 'adds methods with default value on both methods' do
41
+ expect(instance.nick_name)
42
+ .to eq('John')
43
+ end
44
+
45
+ it 'returns the same instance' do
46
+ expect(instance.name)
47
+ .to be_equal(other.name)
48
+ end
49
+ end
50
+
51
+ describe '#default_reader' do
52
+ let(:klass) do
53
+ Class.new do |clazz|
54
+ clazz.send(:attr_writer, :name)
55
+ clazz.send(:default_reader, :name, 'John Doe')
56
+ end
57
+ end
58
+
59
+ it 'adds method returning default value' do
60
+ expect(instance.name).to eq('John Doe')
61
+ end
62
+
63
+ context 'when value is changed' do
64
+ before do
65
+ instance.name = 'Joe'
66
+ end
67
+
68
+ it 'returns new value' do
69
+ expect(instance.name).to eq('Joe')
70
+ end
71
+
72
+ context 'when it is changed to nil' do
73
+ before do
74
+ instance.name = nil
75
+ end
76
+
77
+ it { expect(instance.name).to be_nil }
78
+ end
79
+
80
+ context 'when another instance calls the method' do
81
+ it 'does not change the result of another instance' do
82
+ expect(instance.name).not_to eq(other.name)
83
+ end
84
+ end
85
+ end
86
+ end
87
+
88
+ describe '#default_readers' do
89
+ let(:klass) do
90
+ Class.new do |clazz|
91
+ clazz.send(:attr_writer, :cars, :houses)
92
+ clazz.send(:default_readers, :cars, :houses, 'none')
93
+ end
94
+ end
95
+
96
+ it 'adds method returning default value' do
97
+ expect(instance.cars).to eq('none')
98
+ end
99
+
100
+ it 'returns the same instance for both methods' do
101
+ expect(instance.cars).to be_equal(instance.houses)
102
+ end
103
+
104
+ context 'when setting cars' do
105
+ before { instance.cars = ['volvo'] }
106
+
107
+ it 'sets the value' do
108
+ expect(instance.cars).to eq(['volvo'])
109
+ end
110
+
111
+ it 'does not change the value on the other method' do
112
+ expect(instance.houses).to eq('none')
113
+ end
114
+
115
+ context 'when setting to nil' do
116
+ before { instance.cars = nil }
117
+
118
+ it { expect(instance.cars).to be_nil }
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Date do
6
+ describe 'readme' do
7
+ subject(:date) { described_class.new(2106, 10, 11) }
8
+
9
+ let(:future) { date + 1.year }
10
+ let(:past) { date - 1.year }
11
+
12
+ it 'returns days between' do
13
+ expect(date.days_between(future)).to eq(365)
14
+ end
15
+
16
+ it 'returns positive' do
17
+ expect(date.days_between(past)).to eq(365)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Enumerable do
4
+ describe 'readme' do
5
+ describe '#clean' do
6
+ let(:array) { [1, [], nil, {}, '', hash] }
7
+ let(:hash) { { b: [], c: nil, d: {}, e: '' } }
8
+
9
+ it 'cleans array' do
10
+ expect(array.clean).to eq([1])
11
+ end
12
+ end
13
+
14
+ describe '#clean!' do
15
+ let(:hash) do
16
+ {
17
+ a: 1,
18
+ b: [],
19
+ c: nil,
20
+ d: {},
21
+ e: '',
22
+ f: {
23
+ b: [],
24
+ c: nil,
25
+ d: {},
26
+ e: ''
27
+ }
28
+ }
29
+ end
30
+
31
+ it 'cleans array' do
32
+ expect { hash.clean! }.to change { hash }
33
+ .to(a: 1)
34
+ end
35
+ end
36
+
37
+ describe '#map_and_find' do
38
+ let(:ids) { [10, 21, 30, 31, 51, 55] }
39
+ let(:client) { Client.new(existing_ids) }
40
+ let(:existing_ids) { [1, 11, 21, 31, 41, 51] }
41
+ let(:request) { client.method(:request) }
42
+
43
+ it 'returns the value found' do
44
+ expect(ids.map_and_find(&request)).to eq(id: 21)
45
+ end
46
+
47
+ it 'does not perform all requests all' do
48
+ expect { ids.map_and_find(&request) }
49
+ .to change(client, :requested)
50
+ .from([]).to([10, 21])
51
+ end
52
+ end
53
+
54
+ describe '#map_and_select' do
55
+ let(:ids) { [10, 21, 30, 31, 51, 55] }
56
+ let(:client) { Client.new(existing_ids) }
57
+ let(:existing_ids) { [1, 11, 21, 31, 41, 51] }
58
+ let(:request) { client.method(:request) }
59
+
60
+ it 'returns all values found' do
61
+ expect(ids.map_and_select(&request))
62
+ .to eq([{ id: 21 }, { id: 31 }, { id: 51 }])
63
+ end
64
+ end
65
+
66
+ describe '#map_to_hash' do
67
+ let(:ids) { [10, 21, 30, 31, 51, 55] }
68
+ let(:client) { Client.new(existing_ids) }
69
+ let(:existing_ids) { [1, 11, 21, 31, 41, 51] }
70
+ let(:request) { client.method(:request) }
71
+ let(:expected) do
72
+ {
73
+ 10 => nil,
74
+ 21 => { id: 21 },
75
+ 30 => nil,
76
+ 31 => { id: 31 },
77
+ 51 => { id: 51 },
78
+ 55 => nil
79
+ }
80
+ end
81
+
82
+ it 'returns a hash with the mapped' do
83
+ expect(ids.map_to_hash(&request)).to eq(expected)
84
+ end
85
+ end
86
+ end
87
+ end