darthjee-core_ext 1.7.0 → 1.7.1

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