darthjee-core_ext 1.7.0 → 1.7.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: dd01e58fe4568b6b2c651415bb7677f78265fee8
4
- data.tar.gz: 21b3f51a75beeffad0404ce44696bf57ebe43bf4
3
+ metadata.gz: 7a7679a554bc9075b9a2e6495e47f2602834f106
4
+ data.tar.gz: ae306ba662a111238d997a02c9f178ace1980421
5
5
  SHA512:
6
- metadata.gz: e0df37f38b68eae72c79633ab6e31a0e733591dc63164530b34dc326725a47cb158439813f567e3a7ecb5967ae0b245200001312f905cc4a86a5b067cf3f9e5d
7
- data.tar.gz: 4c4955a0d35d16e0b7ccb1aebedecc8635a6534a58bafb665eb1f827a63e11c1a65809f16a390877cc6f684b08437a702ba87d63e0d2b2e740f548279a6789ea
6
+ metadata.gz: 3a9024a26c829e10daba4866d666a7b9ce0fb5ec92f89b839f5ca06263056326ceb85a400e2f35e416393b2c62123aeaddb42133d764d25fadd829aa525578ec
7
+ data.tar.gz: 4f672dce0e7ea9c55ae670480dfc4306d0776bec49fce1c336d5dfdc15a4927d214c1fe8cb1c5e220255acd47604843efc30bbf985b2c80099f7857e779d256c
data/.gitignore CHANGED
@@ -1,3 +1,5 @@
1
1
  coverage
2
2
  pkg
3
3
  Gemfile.lock
4
+ doc
5
+ .yardoc
data/README.md CHANGED
@@ -7,6 +7,10 @@ Darthjee/CoreExt
7
7
  [![Test Coverage](https://codeclimate.com/github/darthjee/core_ext/badges/coverage.svg)](https://codeclimate.com/github/darthjee/core_ext/coverage)
8
8
  [![Issue Count](https://codeclimate.com/github/darthjee/core_ext/badges/issue_count.svg)](https://codeclimate.com/github/darthjee/core_ext)
9
9
 
10
+ Yard Documentation
11
+ -------------------
12
+ https://www.rubydoc.info/gems/darthjee-core_ext/2.7.1
13
+
10
14
  # Usage
11
15
  This project adds some new methods to the core ruby classes
12
16
 
@@ -24,7 +24,7 @@ Gem::Specification.new do |gem|
24
24
  gem.add_development_dependency 'pry-nav', '~> 0.2.4'
25
25
  gem.add_development_dependency 'rake', '>= 12.3.1'
26
26
  gem.add_development_dependency 'rspec', '>= 3.8'
27
- gem.add_development_dependency 'rubocop', '>= 0.58.1'
27
+ gem.add_development_dependency 'rubocop', '0.58.1'
28
28
  gem.add_development_dependency 'simplecov', '~> 0.16.x'
29
29
  gem.add_development_dependency 'yard', '>= 0.9'
30
30
  end
@@ -2,29 +2,48 @@
2
2
 
3
3
  module Darthjee
4
4
  module CoreExt
5
+ # Module containing new usefull methods to Ruby vanilla Array
5
6
  module Array
6
7
  autoload :HashBuilder, 'darthjee/core_ext/array/hash_builder'
7
8
 
8
- def mapk(*keys)
9
- keys.inject(self) do |enum, key|
10
- enum.map { |hash| hash[key] }
11
- end
12
- end
13
-
14
- def procedural_join(mapper = proc(&:to_s))
15
- return '' if empty?
16
- list = dup
17
- prev = first
18
- list[0] = mapper.call(prev).to_s
19
-
20
- list.inject do |string, val|
21
- j = yield(prev, val) if block_given?
22
- "#{string}#{j}#{mapper.call(val)}".tap do
23
- prev = val
24
- end
25
- end
9
+ # Returns a Hash where the values are the elements of the array
10
+ #
11
+ # @param [::Array<::Object>] keys The keys of the hash
12
+ #
13
+ # @return [::Hash] hash built pairing the keys and values
14
+ #
15
+ # @example Creation of hash with symbol keys
16
+ # array = %w[each word one key]
17
+ # array.as_hash(%i[a b c d])
18
+ # # returns
19
+ # # { a: 'each', b: 'word', c: 'one', d: 'key' }
20
+ def as_hash(keys)
21
+ Array::HashBuilder.new(self, keys).build
26
22
  end
27
23
 
24
+ # Maps the array using the given methods on each
25
+ # element of the array
26
+ #
27
+ # @param [::String,::Symbol] methods List of methods to be called
28
+ # sequentially on each element of the array
29
+ #
30
+ # @yield [element] block to be called on each element performing
31
+ # a final mapping
32
+ # @yieldparam [::Object] element element that will receive
33
+ # the method calls in chain
34
+ #
35
+ # @return [::Array] Array with the result of all method calls in chain
36
+ #
37
+ # @example Mapping to string out of float size of strings
38
+ # words = %w(big_word tiny oh_my_god_such_a_big_word)
39
+ # words.chain_map(:size, :to_f, :to_s) # returns ["8.0", "4.0", "25.0"]
40
+ #
41
+ # @example Mapping with a block mapping at the end
42
+ # words = %w(big_word tiny oh_my_god_such_a_big_word)
43
+ #
44
+ # output = words.chain_map(:size) do |size|
45
+ # (size % 2).zero? ? 'even size' : 'odd size'
46
+ # end # returns ["even size", "even size", "odd size"]
28
47
  def chain_map(*methods, &block)
29
48
  result = methods.inject(self) do |array, method|
30
49
  array.map(&method)
@@ -34,14 +53,89 @@ module Darthjee
34
53
  result.map(&block)
35
54
  end
36
55
 
37
- def as_hash(keys)
38
- Array::HashBuilder.new(self, keys).build
56
+ # Maps array chain fetching the keys of the hashes inside
57
+ #
58
+ # @param [::String,::Symbol] keys list of keys to be
59
+ # fetched from hashes inside
60
+ #
61
+ # @return [::Array] Array resulting of chain fetch of keys
62
+ #
63
+ # @example Multi level hash mapping
64
+ # array = [
65
+ # { a: { b: 1 }, b: 2 },
66
+ # { a: { b: 3 }, b: 4 }
67
+ # ]
68
+ # array,mapk(:a) # returns [{ b: 1 }, { b: 3 }]
69
+ # array.mapk(:a, :b) # returns [1, 3]
70
+ #
71
+ # @example Key missing
72
+ # array = [
73
+ # { a: { b: 1 }, b: 2 },
74
+ # { a: { b: 3 }, b: 4 }
75
+ # ]
76
+ # array.mapk(:c) # returns [nil, nil]
77
+ # array.mapk(:c, :d) # returns [nil, nil]
78
+ def mapk(*keys)
79
+ keys.inject(self) do |enum, key|
80
+ enum.map do |hash|
81
+ hash&.[] key
82
+ end
83
+ end
84
+ end
85
+
86
+ # Joins elements in a string using a proc
87
+ # to convert elements to Strig and a block for joining
88
+ #
89
+ # @param [Proc] mapper Proc that will be used to map values
90
+ # to string before joining
91
+ #
92
+ # @yield [previous, nexte]
93
+ # defines the string to be used to join the previous and
94
+ # next element
95
+ # @yieldparam [::Object] previous previous element that was joined
96
+ # @yieldparam [::Object] nexte next element that will be joined
97
+ #
98
+ # @example Addition of positive and negative numbers
99
+ # [1, 2, -3, -4, 5].procedural_join do |_previous, nexte|
100
+ # nexte.positive? ? '+' : ''
101
+ # end # returns '1+2-3-4+5'
102
+ #
103
+ # @example Spaced addition of positive and negative numbers
104
+ # mapper = proc { |value| value.to_f.to_s }
105
+ # array.procedural_join(mapper) do |_previous, nexte|
106
+ # nexte.positive? ? ' +' : ' '
107
+ # end # returns '1.0 +2.0 -3.0 -4.0 +5.0'
108
+ def procedural_join(mapper = proc(&:to_s))
109
+ return '' if empty?
110
+ list = dup
111
+ previous = first
112
+ list[0] = mapper.call(previous).to_s
113
+
114
+ list.inject do |string, value|
115
+ link = yield(previous, value) if block_given?
116
+ next_string = mapper.call(value)
117
+ previous = value
118
+
119
+ "#{string}#{link}#{next_string}"
120
+ end
39
121
  end
40
122
 
123
+ # Reeturns a random element of the array without altering it
124
+ #
125
+ # @example Picking a random element of numeric array
126
+ # array = [10, 20, 30]
127
+ # array.random # might return 10, 20 or 30
128
+ # array # returns unchanged [10, 20, 30]
41
129
  def random
42
130
  self[rand(size)]
43
131
  end
44
132
 
133
+ # Reeturns a random element of the array removing it from the array
134
+ #
135
+ # @example Slicing a random element of a numeric array
136
+ # array = [10, 20, 30]
137
+ # array.random! # might return 10, 20 or 30 ... lets say 20
138
+ # array # returns changed [20, 30]
45
139
  def random!
46
140
  slice!(rand(size))
47
141
  end
@@ -49,6 +143,16 @@ module Darthjee
49
143
  end
50
144
  end
51
145
 
146
+ # Ruby Array received
147
+ #
148
+ # - mapk
149
+ # - procedural_join
150
+ # - chain_map
151
+ # - as_hash
152
+ # - random
153
+ # - random!
154
+ #
155
+ # @see Darthjee::CoreExt::Array
52
156
  class Array
53
157
  include Darthjee::CoreExt::Array
54
158
  end
@@ -3,14 +3,41 @@
3
3
  module Darthjee
4
4
  module CoreExt
5
5
  module Array
6
+ # Class responsible for building a Hash from 2 arrays
7
+ #
8
+ # @attribute [::Array] values
9
+ # values of the hash to be built
10
+ # @attribute [::Array] keys
11
+ # keys of the hash to be built
12
+ #
13
+ # @example Building the hash from the array
14
+ # values = [10, 20, 30]
15
+ # keys = %i[a b c]
16
+ # builder = Darthjee::CoreExt::Array::HashBuilder.new(values, keys)
17
+ #
18
+ # builder.build # returns { a: 10, b: 20, c: 30 }
19
+ #
20
+ # @example Rebuilding a hash from values and keys
21
+ # hash = { a: 20, b: 200, c: 2000 }
22
+ # builder = Darthjee::CoreExt::Array::HashBuilder.new(
23
+ # hash.values,
24
+ # hash.keys
25
+ # )
26
+ #
27
+ # builder.build == hash # returns true
6
28
  class HashBuilder
7
29
  attr_accessor :values, :keys
8
30
 
31
+ # @param [::Array] values List of values of the hash
32
+ # @param [::Array] keys List of keys of the hash
9
33
  def initialize(values, keys)
10
34
  @values = values.dup
11
35
  @keys = keys.dup
12
36
  end
13
37
 
38
+ # Builds the hash
39
+ # @return [::Hash] Hash whose keys and values are paired
40
+ # from builder's keys and values
14
41
  def build
15
42
  fixes_sizes
16
43
 
@@ -5,10 +5,81 @@ module Darthjee
5
5
  module Class
6
6
  private
7
7
 
8
+ # @!visibility public
9
+ # Adds a method that will return a default value
10
+ #
11
+ # the value is evaluated on class definition, meaning that
12
+ # everytime it is called it will be the same instance
13
+ #
14
+ # @param [::Symbol,::String] name Name of the method to be added
15
+ # @param [::Object] value default value
16
+ #
17
+ # @example Defining a default value
18
+ # class MyClass
19
+ # default_value :name, 'John'
20
+ # end
21
+ #
22
+ # MyClass.new.name # returns 'John'
23
+ #
24
+ # @example Comparing value across instances
25
+ # # frozen_string_literal: false
26
+ #
27
+ # class MyClass
28
+ # default_value :name, 'John'
29
+ # end
30
+ #
31
+ # instance = MyClass.new
32
+ # other = MyClass.new
33
+ #
34
+ # instance.name.equal?('John') # returns false
35
+ # instance.name.equal?(other.name) # returns true
8
36
  def default_value(name, value)
9
37
  define_method(name) { |*_| value }
10
38
  end
11
39
 
40
+ # @!visibility public
41
+ # Adds methods that will return a default value
42
+ #
43
+ # the value is evaluated on class definition, meaning that
44
+ # everytime any of them are called they will return the same instance
45
+ # of value
46
+ #
47
+ # @param [::Array<::Symbol,::String>] names Names of the
48
+ # methods to be added
49
+ # @param [::Object] value default value
50
+ #
51
+ # @example Defining a default values
52
+ # class MyClass
53
+ # default_values :name, :nick_name, 'John'
54
+ # end
55
+ #
56
+ # MyClass.new.name # returns 'John'
57
+ # MyClass.new.nick_name # returns 'John'
58
+ #
59
+ # @example Comparing value across instances
60
+ # # frozen_string_literal: false
61
+ #
62
+ # class MyClass
63
+ # default_values :name, :nick_name, 'John'
64
+ # end
65
+ #
66
+ # instance = MyClass.new
67
+ # other = MyClass.new
68
+ #
69
+ # instance.name.equal?('John') # returns false
70
+ # instance.name.equal?(other.name) # returns true
71
+ #
72
+ # @example Comparing value across methods
73
+ # # frozen_string_literal: false
74
+ #
75
+ # class MyClass
76
+ # default_values :name, :nick_name, 'John'
77
+ # end
78
+ #
79
+ # instance = MyClass.new
80
+ #
81
+ # instance.nick_name.equal?('John') # returns false
82
+ # instance.nick_name.equal?(instance.name) # returns true
12
83
  def default_values(*names, value)
13
84
  names.each do |name|
14
85
  default_value(name, value)
@@ -3,6 +3,28 @@
3
3
  module Darthjee
4
4
  module CoreExt
5
5
  module Date
6
+ # Calculates the number of days between 2 dates
7
+ #
8
+ # @param [::Date,::Time] other_date future/past date for comparisom
9
+ # @return [::Integer] days between two dates
10
+ #
11
+ # @example One year apart date
12
+ # date = Date.new(2018, 11, 21)
13
+ # other_date = Date.new(2019, 11, 21)
14
+ #
15
+ # date.days_between(other_date)) # returns 365
16
+ #
17
+ # @example Four year apart date (having a leap year)
18
+ # date = Date.new(2018, 11, 21)
19
+ # other_date = Date.new(2014, 11, 21)
20
+ #
21
+ # date.days_between(other_date)) # returns 365 * 4 + 1 = 1461
22
+ #
23
+ # @example Checking against time
24
+ # date = Date.new(2018, 11, 21)
25
+ # time = Time.new(2017, 11, 21, 12, 0, 0)
26
+ #
27
+ # date.days_between(time)) # returns 365
6
28
  def days_between(other_date)
7
29
  (self - other_date.to_date).abs
8
30
  end
@@ -5,8 +5,25 @@ module Enumerable
5
5
  deep_dup.clean!
6
6
  end
7
7
 
8
- # delete hash or array values if value is nil
9
- # ex: { a: nil, b: 2 }.clean! => { b: 2 }
8
+ # Removes any element that is nil or empty
9
+ #
10
+ # @returns [::Enumerable] the enumerable itself
11
+ #
12
+ # @example cleaning a Hash
13
+ # hash = {
14
+ # keep: 'value',
15
+ # nil_value: nil,
16
+ # empty_array: [],
17
+ # empty_string: '',
18
+ # empty_hash: {}
19
+ # }
20
+ # hash.clean! # changes the hash to
21
+ # # { keep: 'value' }
22
+ #
23
+ # @example cleaning an Array
24
+ # array = ['value', nil, [], '', {}]
25
+ # array.clean! # changes the array to be
26
+ # # ['value']
10
27
  def clean!
11
28
  if is_a?(Hash)
12
29
  delete_if { |_k, v| empty_value?(v) }
@@ -15,6 +32,31 @@ module Enumerable
15
32
  end
16
33
  end
17
34
 
35
+ # Maps the elements into a new value, returning
36
+ # the first element that is evaluated to true
37
+ #
38
+ # This method is equivalent to #map#find but
39
+ # only calling the map block up to when a value
40
+ # is found
41
+ #
42
+ # @yield (*args) mappig block
43
+ #
44
+ # @example Using an array of keys to remove remove elements of a hash
45
+ #
46
+ # service_map = {
47
+ # a: nil,
48
+ # b: false,
49
+ # c: 'found me',
50
+ # d: nil,
51
+ # e: 'didnt find me'
52
+ # }
53
+ #
54
+ # keys = %i[a b c d e]
55
+ #
56
+ # keys.map_and_find { |key| service_values.delete(key) }
57
+ # # returns 'found me'
58
+ # service_map # has lost only 3 keys returning
59
+ # # { d: nil, e: 'didnt find me' }
18
60
  def map_and_find
19
61
  mapped = nil
20
62
  find do |*args|
@@ -23,6 +65,25 @@ module Enumerable
23
65
  mapped || nil
24
66
  end
25
67
 
68
+ # Maps the elements into a new value returning an
69
+ # array of the values mapped to non false values
70
+ #
71
+ # This method is equivalent to call #map#select
72
+ #
73
+ # @yield (*args) mapping block
74
+ #
75
+ # @example Mapping the values of hash to their size
76
+ # hash = {
77
+ # a: nil,
78
+ # b: 'aka',
79
+ # c: 'a'
80
+ # }
81
+ #
82
+ # values = hash.map_and_select do |key, value|
83
+ # value && value.to_s
84
+ # end
85
+ #
86
+ # values # returns [3, 1]
26
87
  def map_and_select
27
88
  mapped = map do |*args|
28
89
  yield(*args)
@@ -30,6 +91,15 @@ module Enumerable
30
91
  mapped.select { |e| e }
31
92
  end
32
93
 
94
+ # Maps values and creates a hash whose values are
95
+ # the result of the #map and the keys are the original values
96
+ #
97
+ # @yield (*args) the mapping block
98
+ #
99
+ # @example Mapping strings to their sizes
100
+ # strings = %w[word big_word]
101
+ #
102
+ # strings.map_to_hash(&:size) # returns { 'word' => 4, 'big_word' => 8 }
33
103
  def map_to_hash
34
104
  {}.tap do |hash|
35
105
  each do |element|
@@ -4,24 +4,132 @@ module Darthjee
4
4
  module CoreExt
5
5
  module Hash
6
6
  module Transformable
7
- def squash
8
- Hash::Squasher.squash(self)
7
+ # Merges both hashes not adding keys that don't
8
+ # exist in the original hash
9
+ #
10
+ # @param [::Hash] other other hash to be merged
11
+ #
12
+ # @return [::Hash] the merged hash
13
+ #
14
+ # @example merging of hashes with some clashing keys
15
+ # hash = { a: 1, b: 2, c: 3 }
16
+ # other = { b: 4, 'c' => 5, e: 6 }
17
+ #
18
+ # hash.exclusive_merge(other) # returns { a: 1, b: 4, c: 3 }
19
+ # hash # returns { a: 1, b: 2, c: 3 }
20
+ def exclusive_merge(other)
21
+ dup.exclusive_merge!(other)
9
22
  end
10
23
 
11
- def to_deep_hash(separator = '.')
12
- Hash::DeepHashConstructor.new(separator).deep_hash(self)
24
+ # Merges both hashes not adding keys that don't
25
+ # exist in the original hash
26
+ #
27
+ # @param [::Hash] other other hash to be merged
28
+ #
29
+ # @return [::Hash] the merged hash
30
+ #
31
+ # @example merging of hashes with some clashing keys
32
+ # hash = { a: 1, b: 2, c: 3 }
33
+ # other = { b: 4, 'c' => 5, e: 6 }
34
+ #
35
+ # hash.exclusive_merge!(other) # returns { a: 1, b: 4, c: 3 }
36
+ # hash # returns { a: 1, b: 4, c: 3 }
37
+ def exclusive_merge!(other)
38
+ merge!(other.slice(*keys))
13
39
  end
14
40
 
41
+ # Run map block where each pair key, value is mapped
42
+ # to a new value to be assigned in the same key on the
43
+ # returned hash
44
+ #
45
+ # @return new Hash made with the pairs key => mapped_value
46
+ #
47
+ # @yield (key, value) block returning the new value
48
+ #
49
+ # @see ToHashMapper
50
+ #
51
+ # @example mapping to size of the original words
52
+ # hash = { a: 'word', b: 'bigword', c: 'c' }
53
+ #
54
+ # new_hash = hash.map_to_hash do |key, value|
55
+ # "#{key}->#{value.size}"
56
+ # end
57
+ #
58
+ # new_hash # returns { a: 'a->4', b: 'b->7', c: 'c->1' }
15
59
  def map_to_hash(&block)
16
60
  Hash::ToHashMapper.new(self).map(&block)
17
61
  end
18
62
 
19
- def exclusive_merge(hash)
20
- dup.exclusive_merge!(hash)
63
+ # Squash the hash so that it becomes a single level hash
64
+ # merging the keys of outter and inner hashes
65
+ #
66
+ # This operation is the oposite of {#to_deep_hash}
67
+ #
68
+ # @return [::Hash] A one level hash
69
+ #
70
+ # @see Squash::Builder
71
+ # @see #to_deep_hash
72
+ #
73
+ # @example a name hash
74
+ # hash = { name: { first: 'John', last: 'Doe' } }
75
+ #
76
+ # hash.squash # returns {
77
+ # # 'name.first' => 'John',
78
+ # # 'name.last' => 'Doe'
79
+ # # }
80
+ #
81
+ # @example Reverting a #to_deep_hash call
82
+ # person_data = {
83
+ # 'person.name' => 'John',
84
+ # 'person.age' => 23
85
+ # }
86
+ # person = person_data.to_deep_hash
87
+ #
88
+ # person.squash # returns {
89
+ # # 'person.name' => 'John',
90
+ # # 'person.age' => 23
91
+ # # }
92
+ def squash
93
+ Hash::Squasher.squash(self)
21
94
  end
22
95
 
23
- def exclusive_merge!(hash)
24
- merge!(hash.slice(*keys))
96
+ # Creates a new hash of multiple levels from a one level
97
+ # hash
98
+ #
99
+ # this operation is the oposite from {#squash}
100
+ #
101
+ # @return [::Hash] A multi-level hash
102
+ #
103
+ # @see Hash::DeepHashConstructor
104
+ # @see #squash
105
+ #
106
+ # @example construction of name hash
107
+ # { 'name_first' => 'John', 'name_last' => 'Doe' }
108
+ #
109
+ # hash.to_deep_hash # return {
110
+ # # 'name' => {
111
+ # # 'first' => 'John',
112
+ # # 'last' => 'Doe'
113
+ # # }
114
+ # # }
115
+ # @example Reverting squash
116
+ # person = {
117
+ # 'person' => {
118
+ # 'name' => 'John',
119
+ # 'age' => 23
120
+ # }
121
+ # }
122
+ # person_data = person.squash
123
+ #
124
+ # person_data.to_deep_hash
125
+ # # returns {
126
+ # # 'person' => {
127
+ # # 'name' => 'John',
128
+ # # 'age' => 23
129
+ # # }
130
+ # # }
131
+ def to_deep_hash(separator = '.')
132
+ Hash::DeepHashConstructor.new(separator).deep_hash(self)
25
133
  end
26
134
  end
27
135
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Darthjee
4
4
  module CoreExt
5
- VERSION = '1.7.0'
5
+ VERSION = '1.7.1'
6
6
  end
7
7
  end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Darthjee::CoreExt::Array::HashBuilder do
6
+ describe 'yard' do
7
+ describe '#build' do
8
+ subject { described_class.new(values, keys) }
9
+
10
+ let(:values) { [10, 20, 30] }
11
+ let(:keys) { %i[a b c] }
12
+
13
+ it 'builds a hash pairing the keys and values' do
14
+ expect(subject.build).to eq(
15
+ a: 10, b: 20, c: 30
16
+ )
17
+ end
18
+
19
+ context 'when trying to rebuild a hash' do
20
+ let(:hash) { { a: 20, b: 200, c: 2000 } }
21
+ let(:values) { hash.values }
22
+ let(:keys) { hash.keys }
23
+
24
+ it 'rebuilds the original hash' do
25
+ expect(subject.build).to eq(hash)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,123 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Array do
6
+ describe 'yard' do
7
+ describe '#mapk' do
8
+ let(:array) { [{ a: { b: 1 }, b: 2 }, { a: { b: 3 }, b: 4 }] }
9
+
10
+ describe 'when passing just the first key' do
11
+ it 'returns the array mapped ' do
12
+ expect(array.mapk(:a)).to eq([{ b: 1 }, { b: 3 }])
13
+ end
14
+ end
15
+
16
+ describe 'when passing a second key' do
17
+ it 'chain fetches the key' do
18
+ expect(array.mapk(:a, :b)).to eq([1, 3])
19
+ end
20
+ end
21
+
22
+ describe 'when fetching a non existing key' do
23
+ it 'returns nil for value' do
24
+ expect(array.mapk(:c)).to eq([nil, nil])
25
+ end
26
+ end
27
+
28
+ describe 'when element is not a hash' do
29
+ it 'returns nil for value' do
30
+ expect(array.mapk(:c, :d)).to eq([nil, nil])
31
+ end
32
+ end
33
+ end
34
+
35
+ describe '#procedural_join' do
36
+ let(:array) { [1, 2, -3, -4, 5] }
37
+
38
+ context 'when not mapping the value' do
39
+ context 'when creating a sum' do
40
+ let(:result) do
41
+ array.procedural_join do |_previous, nexte|
42
+ nexte.positive? ? '+' : ''
43
+ end
44
+ end
45
+
46
+ it 'creates a sum' do
47
+ expect(result).to eq('1+2-3-4+5')
48
+ end
49
+ end
50
+ end
51
+
52
+ context 'when mapping the value' do
53
+ let(:result) do
54
+ mapper = proc { |value| value.to_f.to_s }
55
+ array.procedural_join(mapper) do |_previous, nexte|
56
+ nexte.positive? ? ' +' : ' '
57
+ end
58
+ end
59
+
60
+ it 'maps the value on the output' do
61
+ expect(result).to eq('1.0 +2.0 -3.0 -4.0 +5.0')
62
+ end
63
+ end
64
+ end
65
+
66
+ describe '#chain_main' do
67
+ let(:words) { %w[big_word tiny oh_my_god_such_a_big_word] }
68
+
69
+ context 'when not passing a block' do
70
+ let(:words) { %w[big_word tiny oh_my_god_such_a_big_word] }
71
+
72
+ it 'calls the methods in a succession to map' do
73
+ output = words.chain_map(:size, :to_f, :to_s)
74
+ expect(output).to eq(%w[8.0 4.0 25.0])
75
+ end
76
+ end
77
+
78
+ context 'when passing a block' do
79
+ it 'mapps with the block at the end' do
80
+ output = words.chain_map(:size) do |size|
81
+ (size % 2).zero? ? 'even size' : 'odd size'
82
+ end
83
+ expect(output).to eq(['even size', 'even size', 'odd size'])
84
+ end
85
+ end
86
+ end
87
+
88
+ describe '#as_hash' do
89
+ let(:array) { %w[each word one key] }
90
+ let(:keys) { %i[a b c d] }
91
+
92
+ it 'Uses the keys arra as keys of the hash' do
93
+ expect(array.as_hash(keys)).to eq(
94
+ a: 'each', b: 'word', c: 'one', d: 'key'
95
+ )
96
+ end
97
+ end
98
+
99
+ describe '#random' do
100
+ let(:array) { [10, 20, 30] }
101
+
102
+ it 'returns an element of the array' do
103
+ expect(array).to include(array.random)
104
+ end
105
+
106
+ it do
107
+ expect { array.random }.not_to(change { array })
108
+ end
109
+ end
110
+
111
+ describe '#random!' do
112
+ let(:array) { [10, 20, 30] }
113
+
114
+ it 'returns an element of the array' do
115
+ expect(array.dup).to include(array.random!)
116
+ end
117
+
118
+ it do
119
+ expect { array.random! }.to(change { array })
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: false
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Class do
6
+ describe 'yard' do
7
+ describe '#default_value' do
8
+ subject { klass.new }
9
+
10
+ let(:klass) do
11
+ Class.new do
12
+ default_value :name, 'John'
13
+ end
14
+ end
15
+
16
+ context 'when calling method' do
17
+ it 'returns the same value always' do
18
+ expect(subject.name).to eq('John')
19
+ end
20
+
21
+ it 'returns the same instance accros instances of the class' do
22
+ expect(subject.name).not_to be_equal('John')
23
+ expect(subject.name).to be_equal(klass.new.name)
24
+ end
25
+ end
26
+ end
27
+
28
+ describe '#default_values' do
29
+ subject { klass.new }
30
+
31
+ let(:klass) do
32
+ Class.new do
33
+ default_values :name, :nick_name, 'John'
34
+ end
35
+ end
36
+
37
+ context 'when calling method' do
38
+ it 'returns the same value always' do
39
+ expect(subject.name).to eq('John')
40
+ end
41
+
42
+ it 'returns the same value always' do
43
+ expect(subject.nick_name).to eq('John')
44
+ end
45
+
46
+ it 'returns the same instance accros instances of the class' do
47
+ expect(subject.name).not_to be_equal('John')
48
+ expect(subject.name).to be_equal(klass.new.name)
49
+ end
50
+
51
+ it 'returns the same instance for all methods' do
52
+ expect(subject.nick_name).not_to be_equal('John')
53
+ expect(subject.name).to be_equal(subject.nick_name)
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Date do
6
+ describe 'yard' do
7
+ describe '#days_between' do
8
+ subject { Date.new(2018, 11, 21) }
9
+
10
+ context 'when checking against another date' do
11
+ let(:other_date) { Date.new(2019, 11, 21) }
12
+
13
+ it 'returns the days between' do
14
+ expect(subject.days_between(other_date)).to eq(365)
15
+ end
16
+ end
17
+
18
+ context 'when cheking agains a 4 years apart date' do
19
+ let(:other_date) { Date.new(2014, 11, 21) }
20
+
21
+ it 'returns the days between' do
22
+ expect(subject.days_between(other_date)).to eq(1461)
23
+ end
24
+ end
25
+
26
+ context 'when checking against time' do
27
+ let(:time) { Time.new(2017, 11, 21, 12, 0, 0) }
28
+
29
+ it 'ignores the hours' do
30
+ expect(subject.days_between(time)).to eq(365)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Enumerable do
6
+ describe 'yard' do
7
+ describe '#clean!' do
8
+ context 'when subject is a hash' do
9
+ subject(:hash) do
10
+ {
11
+ keep: 'value',
12
+ nil_value: nil,
13
+ empty_array: [],
14
+ empty_string: '',
15
+ empty_hash: {}
16
+ }
17
+ end
18
+
19
+ it 'removes empty values' do
20
+ expect { hash.clean! }.to change { hash }.to(keep: 'value')
21
+ end
22
+ end
23
+
24
+ context 'when subject is an array' do
25
+ subject(:array) do
26
+ ['value', nil, [], '', {}]
27
+ end
28
+
29
+ it 'removes empty values' do
30
+ expect { array.clean! }.to change { array }.to(['value'])
31
+ end
32
+ end
33
+ end
34
+
35
+ describe '#map_and_find' do
36
+ subject(:keys) { %i[a b c d e] }
37
+
38
+ let(:service_values) do
39
+ {
40
+ a: nil,
41
+ b: false,
42
+ c: 'found me',
43
+ d: nil,
44
+ e: 'didnt find me'
45
+ }
46
+ end
47
+
48
+ it 'returns the first non false value' do
49
+ value = keys.map_and_find { |key| service_values.delete(key) }
50
+ expect(value).to eq('found me')
51
+ end
52
+
53
+ it 'stops running when value is found' do
54
+ expect do
55
+ keys.map_and_find { |key| service_values.delete(key) }
56
+ end.to change { service_values }.to(d: nil, e: 'didnt find me')
57
+ end
58
+ end
59
+
60
+ describe '#map_and_select' do
61
+ subject(:hash) do
62
+ {
63
+ a: nil,
64
+ b: 'aka',
65
+ c: 'a'
66
+ }
67
+ end
68
+
69
+ it 'returns the first non false value' do
70
+ array = hash.map_and_select { |_key, value| value&.size }
71
+ expect(array).to eq([3, 1])
72
+ end
73
+ end
74
+
75
+ describe 'map_to_hash' do
76
+ subject(:strings) { %w[word big_word] }
77
+
78
+ it 'returns a hash with the mapped values' do
79
+ hash = strings.map_to_hash(&:size)
80
+ expect(hash).to eq('word' => 4, 'big_word' => 8)
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Hash do
6
+ describe 'yard' do
7
+ describe '#exclusive_merge' do
8
+ subject(:hash) { { a: 1, b: 2, c: 3 } }
9
+ let(:other) { { b: 4, 'c' => 5, e: 6 } }
10
+
11
+ it 'merges only the existing keys' do
12
+ expect(hash.exclusive_merge(other)).to eq(a: 1, b: 4, c: 3)
13
+ end
14
+
15
+ it 'does not change original hash' do
16
+ expect do
17
+ hash.exclusive_merge(other)
18
+ end.not_to(change { hash })
19
+ end
20
+ end
21
+
22
+ describe '#exclusive_merge' do
23
+ subject(:hash) { { a: 1, b: 2, c: 3 } }
24
+ let(:other) { { b: 4, 'c' => 5, e: 6 } }
25
+
26
+ it 'merges only the existing keys' do
27
+ expect(hash.exclusive_merge!(other)).to eq(a: 1, b: 4, c: 3)
28
+ end
29
+
30
+ it 'does not change original hash' do
31
+ expect do
32
+ hash.exclusive_merge!(other)
33
+ end.to change { hash }.to(a: 1, b: 4, c: 3)
34
+ end
35
+ end
36
+ end
37
+
38
+ describe '#map_to_hash' do
39
+ subject(:hash) { { a: 'word', b: 'bigword', c: 'c' } }
40
+
41
+ it 'remaps the values keeping the original keys' do
42
+ new_hash = hash.map_to_hash do |key, value|
43
+ "#{key}->#{value.size}"
44
+ end
45
+
46
+ expect(new_hash).to eq(
47
+ a: 'a->4',
48
+ b: 'b->7',
49
+ c: 'c->1'
50
+ )
51
+ end
52
+ end
53
+
54
+ describe '#squash' do
55
+ subject(:hash) { { name: { first: 'John', last: 'Doe' } } }
56
+
57
+ it 'squash the hash into a one level hash' do
58
+ expect(hash.squash).to eq('name.first' => 'John', 'name.last' => 'Doe')
59
+ end
60
+
61
+ context 'when squashing the result of a deep hash' do
62
+ let(:person_data) { { 'person.name' => 'John', 'person.age' => 23 } }
63
+ let(:person) { person_data.to_deep_hash }
64
+
65
+ it 'is the reverse operation' do
66
+ expect(person.squash).to eq(person_data)
67
+ end
68
+ end
69
+ end
70
+
71
+ describe '#to_deep_hash' do
72
+ subject(:hash) { { 'name_first' => 'John', 'name_last' => 'Doe' } }
73
+
74
+ it 'with custom separator' do
75
+ expect(hash.to_deep_hash('_')).to eq(
76
+ 'name' => { 'first' => 'John', 'last' => 'Doe' }
77
+ )
78
+ end
79
+
80
+ context 'when squashing the result of a deep hash' do
81
+ let(:person) do
82
+ {
83
+ 'person' => {
84
+ 'name' => 'John',
85
+ 'age' => 23
86
+ }
87
+ }
88
+ end
89
+ let(:person_data) { person.squash }
90
+
91
+ it 'is the reverse operation' do
92
+ expect(person_data.to_deep_hash).to eq(person)
93
+ end
94
+ end
95
+ end
96
+ end
@@ -11,6 +11,18 @@ describe Array do
11
11
  it 'maps using the keys given as arguments' do
12
12
  expect(array.mapk(:a, :b)).to eq([1, 3])
13
13
  end
14
+
15
+ describe 'when fetching a non existing key' do
16
+ it 'returns nil for value' do
17
+ expect(array.mapk(:c)).to eq([nil, nil])
18
+ end
19
+ end
20
+
21
+ describe 'when element is not a hash' do
22
+ it do
23
+ expect(array.mapk(:c, :d)).to eq([nil, nil])
24
+ end
25
+ end
14
26
  end
15
27
 
16
28
  describe '#procedural_join' do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: darthjee-core_ext
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.7.0
4
+ version: 1.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Darthjee
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-09-06 00:00:00.000000000 Z
11
+ date: 2018-10-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -84,14 +84,14 @@ dependencies:
84
84
  name: rubocop
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - ">="
87
+ - - '='
88
88
  - !ruby/object:Gem::Version
89
89
  version: 0.58.1
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - ">="
94
+ - - '='
95
95
  - !ruby/object:Gem::Version
96
96
  version: 0.58.1
97
97
  - !ruby/object:Gem::Dependency
@@ -172,6 +172,12 @@ files:
172
172
  - lib/darthjee/core_ext/time.rb
173
173
  - lib/darthjee/core_ext/version.rb
174
174
  - mech.jpg
175
+ - spec/integration/yard/array/hash_builder_spec.rb
176
+ - spec/integration/yard/array_spec.rb
177
+ - spec/integration/yard/class/default_value_spec.rb
178
+ - spec/integration/yard/date/days_between_spec.rb
179
+ - spec/integration/yard/enumerable_spec.rb
180
+ - spec/integration/yard/hash/transformable_spec.rb
175
181
  - spec/lib/array_spec.rb
176
182
  - spec/lib/class_spec.rb
177
183
  - spec/lib/darthjee/core_ext/hash/chain_fetcher_spec.rb
@@ -232,6 +238,12 @@ signing_key:
232
238
  specification_version: 4
233
239
  summary: Core Extensions
234
240
  test_files:
241
+ - spec/integration/yard/array/hash_builder_spec.rb
242
+ - spec/integration/yard/array_spec.rb
243
+ - spec/integration/yard/class/default_value_spec.rb
244
+ - spec/integration/yard/date/days_between_spec.rb
245
+ - spec/integration/yard/enumerable_spec.rb
246
+ - spec/integration/yard/hash/transformable_spec.rb
235
247
  - spec/lib/array_spec.rb
236
248
  - spec/lib/class_spec.rb
237
249
  - spec/lib/darthjee/core_ext/hash/chain_fetcher_spec.rb