augmented 0.0.1 → 0.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ab72b071901020afba04d0c492f1bc6363545a2b
4
- data.tar.gz: 529677d1369c9d9125212faa80a6f71cef648e81
3
+ metadata.gz: c45e4c37723b2e38793bb1476b7be8e8662b8c4a
4
+ data.tar.gz: c988abdf0493e83cb1b8406af472649fe6f10d00
5
5
  SHA512:
6
- metadata.gz: 3376e35d3240db0dd12e8dca2ae0798200d8b75fda9b1a6b90d6c6638de1f5d2df8dda2d26ca0763dd8b9e20f24183c9930005f1bf5cdb168a33c2985fc2a65c
7
- data.tar.gz: 09f783c3f13bd508fe7d012955ade5c12d7c9dce2e215fa7d065a72669567a06cad27c3478d3a391d55386a8a5a01f334c0ec696d667dd67593a6cf37b6aff0f
6
+ metadata.gz: 9e87a5bf8e30edfc41f7364f6b5851bccbbe15cbe1d908d4ad7471793ea4129dfb254ae3963257fc0f61c378e6c96be43be480d8d735864e3923f9c28a43e155
7
+ data.tar.gz: 19b0e83ca99b904f0f69614966649e7e26c70210ca6da3862a21ded599e4e934d249b4d08c36e9c3ec71d3d785d6e3861abf5ca72b3ad5accb4368ca9eb3085c
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  `Augmented` is a library with some core-type utility methods that I frequently find myself copying across projects. It uses refinements instead of class modification for maximum control and an easy sleep at night.
4
4
 
5
- Many of the methods in `Augmented` facilitate a more functional style of programming and cover a few tiny gaps in Ruby's solid functional support.
5
+ Many of the methods in `Augmented` facilitate a more functional style of programming and cover a few tiny gaps in Ruby's solid functional support. See more thoughts on this [blog post](http://blog.brunze.com/2015/using-ruby-refinements-fun-flow/).
6
6
 
7
7
  ## Installation
8
8
 
@@ -27,18 +27,19 @@ using Augmented
27
27
  You can load all refinements for just one type:
28
28
 
29
29
  ```ruby
30
- using Augmented::Objects
30
+ using Augmented::Enumerators
31
31
  using Augmented::Hashes
32
+ using Augmented::Objects
33
+ using Augmented::Procs
32
34
  using Augmented::Symbols
33
- # etc.
34
35
  ```
35
36
 
36
37
  Or you can load just the methods you need:
37
38
 
38
39
  ```ruby
39
40
  using Augmented::Objects::Pickable
40
- using Augmented::Symbols::Arguable
41
41
  using Augmented::Procs::Chainable
42
+ using Augmented::Symbols::Arguable
42
43
  # etc.
43
44
  ```
44
45
 
@@ -49,15 +50,41 @@ using Augmented::Procs::Chainable
49
50
  Builds an index of all elements of an enumerator according to the given criterion.
50
51
 
51
52
  ```ruby
53
+ using Augmented::Enumerators::Indexing
54
+
52
55
  ['a', 'bb', 'ccccc'].to_enum.index_by(&:length)
53
56
  # {1=>"a", 2=>"bb", 5=>"ccccc"}
54
57
  ```
55
58
 
59
+ ##### `Hash#map_values`
60
+
61
+ Returns a new hash with the same keys but transformed values.
62
+
63
+ ```ruby
64
+ using Augmented::Hashes::Mappable
65
+
66
+ { aa: 11, bb: 22 }.map_values{ |i| i * 3 }
67
+ # {:aa=>33, :bb=>66}
68
+ ```
69
+
70
+ ##### `Hash#map_keys`
71
+
72
+ Returns a new hash with the same values but transformed keys.
73
+
74
+ ```ruby
75
+ using Augmented::Hashes::Mappable
76
+
77
+ { aa: 11, bb: 22 }.map_keys{ |k| k.to_s[0] }
78
+ # {"a"=>11, "b"=>22}
79
+ ```
80
+
56
81
  ##### `Hash#polymorph`
57
82
 
58
- Creates an object from an Hash.
83
+ Creates an object from a Hash.
59
84
 
60
85
  ```ruby
86
+ using Augmented::Hashes::Polymorphable
87
+
61
88
  class Sheep
62
89
  def initialize attributes
63
90
  @sound = attributes[:sound]
@@ -77,6 +104,8 @@ end
77
104
  Recursively applies functions to a tree of hashes.
78
105
 
79
106
  ```ruby
107
+ using Augmented::Hashes::Transformable
108
+
80
109
  tree = { lorem: 'ipsum', dolor: [ { sit: 10}, { sit: 20 } ] }
81
110
  triple = -> i { i * 3 }
82
111
 
@@ -84,11 +113,24 @@ tree.transform({ lorem: :upcase, dolor: { sit: triple } })
84
113
  # {:lorem=>"IPSUM", :dolor=>[{:sit=>30}, {:sit=>60}]}
85
114
  ```
86
115
 
116
+ ##### `Object#if`, `Object#else`
117
+
118
+ Allows you to conditionally return an object, increasing readability in some situations.
119
+
120
+ ```ruby
121
+ using Augmented::Objects::Iffy
122
+
123
+ Person.new.eat toast.if(toast.buttered?).else(muffin)
124
+ Person.new.eat toast.if(&:buttered?).else(muffin)
125
+ ```
126
+
87
127
  ##### `Object#pick`
88
128
 
89
129
  Calls a bunch of methods on an object and collects the results.
90
130
 
91
131
  ```ruby
132
+ using Augmented::Objects::Pickable
133
+
92
134
  class MyThing
93
135
  def lorem; 'hello'; end
94
136
  def ipsum; 'cruel'; end
@@ -104,15 +146,30 @@ MyThing.new.pick :lorem, :dolor
104
146
  Appends a bunch of singleton methods to an object.
105
147
 
106
148
  ```ruby
149
+ using Augmented::Objects::Tackable
150
+
107
151
  Object.new.tack(id: 11, greet: -> { puts "hello I'm #{id}" }).greet
108
152
  # hello I'm 11
109
153
  ```
110
154
 
155
+ ##### `Object#tap_if`, `Object#tap_unless`
156
+
157
+ Like [`tap`](http://ruby-doc.org/core-2.2.3/Object.html#method-i-tap) but only executes the block according to the condition.
158
+
159
+ ```ruby
160
+ using Augmented::Objects::Tappable
161
+
162
+ toast.tap_if(toast.warm?){ |toast| toast.butter }.eat
163
+ toast.tap_if(:warm?.to_proc){ |toast| toast.butter }.eat
164
+ ```
165
+
111
166
  ##### `Object#thru`
112
167
 
113
168
  Applies a function to an object and returns the result.
114
169
 
115
170
  ```ruby
171
+ using Augmented::Objects::Thru
172
+
116
173
  filter_words = -> s { s.gsub(/bad/, '').squeeze(' ').strip }
117
174
 
118
175
  'BAD WORDS, BAD WORDS'.downcase.thru(&filter_words).capitalize
@@ -124,6 +181,8 @@ filter_words = -> s { s.gsub(/bad/, '').squeeze(' ').strip }
124
181
  Chains several procs together so they execute from left to right.
125
182
 
126
183
  ```ruby
184
+ using Augmented::Procs::Chainable
185
+
127
186
  sub_two = -> i { i - 2 }
128
187
  triple = -> i { i * 3 }
129
188
  add_twenty = -> i { i + 20 }
@@ -137,6 +196,8 @@ add_twenty = -> i { i + 20 }
137
196
  Like [`Symbol#to_proc`](http://ruby-doc.org/core-2.3.0/Symbol.html#method-i-to_proc) but allows you to pass some arguments along.
138
197
 
139
198
  ```ruby
199
+ using Augmented::Symbols::Arguable
200
+
140
201
  class Eleven
141
202
  def add_many *others
142
203
  11 + others.reduce(0, :+)
@@ -152,6 +213,8 @@ end
152
213
  Creates functions that compare an object's attribute.
153
214
 
154
215
  ```ruby
216
+ using Augmented::Symbols::Comparing
217
+
155
218
  class User
156
219
  def initialize name
157
220
  @name = name
@@ -0,0 +1,17 @@
1
+ module Augmented
2
+ module Hashes
3
+ module Mappable
4
+ refine Hash do
5
+
6
+ def map_values
7
+ self.each_with_object({}){ |(key, value), result| result[key] = yield value, key, self }
8
+ end
9
+
10
+ def map_keys
11
+ self.each_with_object({}){ |(key, value), result| result[yield key, value, self] = value }
12
+ end
13
+
14
+ end
15
+ end
16
+ end
17
+ end
@@ -1,8 +1,10 @@
1
+ require 'augmented/hashes/mappable'
1
2
  require 'augmented/hashes/polymorphable'
2
3
  require 'augmented/hashes/transformable'
3
4
 
4
5
  module Augmented
5
6
  module Hashes
7
+ include Mappable
6
8
  include Polymorphable
7
9
  include Transformable
8
10
  end
@@ -0,0 +1,34 @@
1
+ module Augmented
2
+ module Objects
3
+ module Iffy
4
+ refine Object do
5
+
6
+ def if condition = self
7
+ self if (block_given? ? yield(self) : condition)
8
+ end
9
+
10
+ def else *_
11
+ self
12
+ end
13
+
14
+ end
15
+
16
+ refine NilClass do
17
+
18
+ def else alternative
19
+ alternative
20
+ end
21
+
22
+ end
23
+
24
+ refine FalseClass do
25
+
26
+ def else alternative
27
+ alternative
28
+ end
29
+
30
+ end
31
+
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,19 @@
1
+ module Augmented
2
+ module Objects
3
+ module Tappable
4
+ refine Object do
5
+
6
+ def tap_if condition, &block
7
+ do_tap = condition.respond_to?(:call) ? condition.call(self) : condition
8
+ do_tap ? self.tap(&block) : self
9
+ end
10
+
11
+ def tap_unless condition, &block
12
+ skip_tap = condition.respond_to?(:call) ? condition.call(self) : condition
13
+ skip_tap ? self : self.tap(&block)
14
+ end
15
+
16
+ end
17
+ end
18
+ end
19
+ end
@@ -1,11 +1,15 @@
1
+ require 'augmented/objects/iffy'
1
2
  require 'augmented/objects/pickable'
2
3
  require 'augmented/objects/tackable'
4
+ require 'augmented/objects/tappable'
3
5
  require 'augmented/objects/thru'
4
6
 
5
7
  module Augmented
6
8
  module Objects
9
+ include Iffy
7
10
  include Pickable
8
11
  include Tackable
12
+ include Tappable
9
13
  include Thru
10
14
  end
11
15
  end
@@ -4,7 +4,7 @@ module Augmented
4
4
  refine Proc do
5
5
 
6
6
  def | other
7
- -> (*args) { other.to_proc.call self.call(*args) }
7
+ -> *args { other.to_proc.call self.call(*args) }
8
8
  end
9
9
 
10
10
  end
@@ -1,3 +1,3 @@
1
1
  module Augmented
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -0,0 +1,37 @@
1
+ require 'minitest/autorun'
2
+ require 'augmented/hashes/mappable'
3
+
4
+ describe Augmented::Hashes::Mappable do
5
+ using Augmented::Hashes::Mappable
6
+
7
+ describe '#map_values' do
8
+
9
+ it 'returns a new hash with the same keys but transformed values' do
10
+ { aa: 11, bb: 22 }.map_values{ |i| i * 3 }.must_equal({ aa: 33, bb: 66 })
11
+ end
12
+
13
+ it 'also provides the key and hash to the tranformer function as additional arguments' do
14
+ hash = { aa: 11, bb: 22 }
15
+ result = hash.map_values{ |i, key, h| [key, h.object_id] }
16
+
17
+ result.values.must_equal [[:aa, hash.object_id], [:bb, hash.object_id]]
18
+ end
19
+
20
+ end
21
+
22
+ describe '#map_keys' do
23
+
24
+ it 'returns a new hash with the same values but transformed keys' do
25
+ { aa: 11, bb: 22 }.map_keys{ |k| k.to_s[0] }.must_equal({ 'a' => 11, 'b' => 22 })
26
+ end
27
+
28
+ it 'also provides the value and hash to the tranformer function as additional arguments' do
29
+ hash = { aa: 11, bb: 22 }
30
+ result = hash.map_keys{ |k, value, h| [value, h.object_id] }
31
+
32
+ result.keys.must_equal [[11, hash.object_id], [22, hash.object_id]]
33
+ end
34
+
35
+ end
36
+
37
+ end
@@ -0,0 +1,47 @@
1
+ require 'minitest/autorun'
2
+ require 'augmented/objects/iffy'
3
+
4
+ describe Augmented::Objects::Iffy do
5
+ using Augmented::Objects::Iffy
6
+
7
+ describe '#if' do
8
+
9
+ it 'returns the object if the condition evaluates to truish' do
10
+ subject = 'abc'
11
+ condition = -> subj { subj.length == 3 }
12
+
13
+ subject.if(true).must_be_same_as subject
14
+ subject.if(Object.new).must_be_same_as subject
15
+ subject.if(&condition).must_be_same_as subject
16
+ end
17
+
18
+ it 'returns nil if the condition evaluates to falsy' do
19
+ subject = 'abc'
20
+ condition = -> subj { subj.length == 0 }
21
+
22
+ subject.if(false).must_be_same_as nil
23
+ subject.if(nil).must_be_same_as nil
24
+ subject.if(&condition).must_be_same_as nil
25
+ end
26
+
27
+ end
28
+
29
+ describe '#else' do
30
+
31
+ it 'returns the alternative if the object is falsy' do
32
+ alternative = Object.new
33
+
34
+ false.else(alternative).must_be_same_as alternative
35
+ nil.else(alternative).must_be_same_as alternative
36
+ end
37
+
38
+ it 'returns the object if the object is truish' do
39
+ subject = Object.new
40
+
41
+ true.else(123).must_be_same_as true
42
+ subject.else(123).must_be_same_as subject
43
+ end
44
+
45
+ end
46
+
47
+ end
@@ -7,7 +7,7 @@ describe Augmented::Objects::Pickable do
7
7
 
8
8
  describe '#pick' do
9
9
 
10
- it 'returns an hash with the results of invoking the list of picks in the target' do
10
+ it 'returns a hash with the results of invoking the list of picks in the target' do
11
11
  target = OpenStruct.new aaa: 111, bbb: 222, ccc: 333
12
12
 
13
13
  target.pick(:aaa, :ccc).must_equal({ aaa: 111, ccc: 333 })
@@ -0,0 +1,141 @@
1
+ require 'minitest/autorun'
2
+ require 'augmented/objects/tappable'
3
+
4
+ describe Augmented::Objects::Tappable do
5
+ using Augmented::Objects::Tappable
6
+
7
+ describe '#tap_if' do
8
+
9
+ it 'executes block if condition is truish' do
10
+ subject = 'abc'
11
+ test = nil
12
+
13
+ subject.tap_if(true) { |subj| test = subj.upcase }
14
+
15
+ test.must_equal 'ABC'
16
+
17
+ subject.tap_if(Object.new) { |subj| test = subj.reverse }
18
+
19
+ test.must_equal 'cba'
20
+ end
21
+
22
+ it 'does not execute block if condition is falsy' do
23
+ subject = 'abc'
24
+ test = nil
25
+
26
+ subject.tap_if(false) { |subj| test = subj.upcase }
27
+
28
+ test.must_equal nil
29
+
30
+ subject.tap_if(nil) { |subj| test = subj.upcase }
31
+
32
+ test.must_equal nil
33
+ end
34
+
35
+ it 'executes block if condition evaluates to truish' do
36
+ subject = 'abc'
37
+ test = nil
38
+ condition_1 = -> subj { subj.length == 3 }
39
+ condition_2 = -> subj { subj.length }
40
+
41
+ subject.tap_if(condition_1) { |subj| test = subj.upcase }
42
+
43
+ test.must_equal 'ABC'
44
+
45
+ subject.tap_if(condition_2) { |subj| test = subj.reverse }
46
+
47
+ test.must_equal 'cba'
48
+ end
49
+
50
+ it 'does not execute block if condition evaluates to falsy' do
51
+ subject = 'abc'
52
+ test = nil
53
+ condition_1 = -> subj { subj.length == 0 }
54
+ condition_2 = -> subj { nil }
55
+
56
+ subject.tap_if(condition_1) { |subj| test = subj.upcase }
57
+
58
+ test.must_equal nil
59
+
60
+ subject.tap_if(condition_2) { |subj| test = subj.upcase }
61
+
62
+ test.must_equal nil
63
+ end
64
+
65
+ it 'always returns the object' do
66
+ subject = 'abc'
67
+
68
+ subject.tap_if(true){}.must_be_same_as subject
69
+ subject.tap_if(false){}.must_be_same_as subject
70
+ end
71
+
72
+ end
73
+
74
+ describe '#tap_unless' do
75
+
76
+ it 'executes block if condition is falsy' do
77
+ subject = 'abc'
78
+ test = nil
79
+
80
+ subject.tap_unless(false) { |subj| test = subj.upcase }
81
+
82
+ test.must_equal 'ABC'
83
+
84
+ subject.tap_unless(nil) { |subj| test = subj.reverse }
85
+
86
+ test.must_equal 'cba'
87
+ end
88
+
89
+ it 'does not execute block if condition is truish' do
90
+ subject = 'abc'
91
+ test = nil
92
+
93
+ subject.tap_unless(true) { |subj| test = subj.upcase }
94
+
95
+ test.must_equal nil
96
+
97
+ subject.tap_unless(Object.new) { |subj| test = subj.upcase }
98
+
99
+ test.must_equal nil
100
+ end
101
+
102
+ it 'executes block if condition evaluates to falsy' do
103
+ subject = 'abc'
104
+ test = nil
105
+ condition_1 = -> subj { subj.length == 0 }
106
+ condition_2 = -> subj { nil }
107
+
108
+ subject.tap_unless(condition_1) { |subj| test = subj.upcase }
109
+
110
+ test.must_equal 'ABC'
111
+
112
+ subject.tap_unless(condition_2) { |subj| test = subj.reverse }
113
+
114
+ test.must_equal 'cba'
115
+ end
116
+
117
+ it 'does not execute block if condition evaluates to truish' do
118
+ subject = 'abc'
119
+ test = nil
120
+ condition_1 = -> subj { subj.length == 3 }
121
+ condition_2 = -> subj { subj.length }
122
+
123
+ subject.tap_unless(condition_1) { |subj| test = subj.upcase }
124
+
125
+ test.must_equal nil
126
+
127
+ subject.tap_unless(condition_2) { |subj| test = subj.upcase }
128
+
129
+ test.must_equal nil
130
+ end
131
+
132
+ it 'always returns the object' do
133
+ subject = 'abc'
134
+
135
+ subject.tap_unless(true){}.must_be_same_as subject
136
+ subject.tap_unless(false){}.must_be_same_as subject
137
+ end
138
+
139
+ end
140
+
141
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: augmented
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - bruno
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-01-04 00:00:00.000000000 Z
11
+ date: 2016-03-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -56,11 +56,14 @@ files:
56
56
  - lib/augmented/enumerators.rb
57
57
  - lib/augmented/enumerators/indexing.rb
58
58
  - lib/augmented/hashes.rb
59
+ - lib/augmented/hashes/mappable.rb
59
60
  - lib/augmented/hashes/polymorphable.rb
60
61
  - lib/augmented/hashes/transformable.rb
61
62
  - lib/augmented/objects.rb
63
+ - lib/augmented/objects/iffy.rb
62
64
  - lib/augmented/objects/pickable.rb
63
65
  - lib/augmented/objects/tackable.rb
66
+ - lib/augmented/objects/tappable.rb
64
67
  - lib/augmented/objects/thru.rb
65
68
  - lib/augmented/procs.rb
66
69
  - lib/augmented/procs/chainable.rb
@@ -69,10 +72,13 @@ files:
69
72
  - lib/augmented/symbols/comparing.rb
70
73
  - lib/augmented/version.rb
71
74
  - test/augmented/enumerators/indexing_test.rb
75
+ - test/augmented/hashes/mappable_test.rb
72
76
  - test/augmented/hashes/polymorphable_test.rb
73
77
  - test/augmented/hashes/transformable_test.rb
78
+ - test/augmented/objects/iffy_test.rb
74
79
  - test/augmented/objects/pickable_test.rb
75
80
  - test/augmented/objects/tackable_test.rb
81
+ - test/augmented/objects/tappable_test.rb
76
82
  - test/augmented/objects/thru_test.rb
77
83
  - test/augmented/procs/chainable_test.rb
78
84
  - test/augmented/symbols/arguable_test.rb
@@ -103,10 +109,13 @@ specification_version: 4
103
109
  summary: Useful extra methods for some Ruby core types.
104
110
  test_files:
105
111
  - test/augmented/enumerators/indexing_test.rb
112
+ - test/augmented/hashes/mappable_test.rb
106
113
  - test/augmented/hashes/polymorphable_test.rb
107
114
  - test/augmented/hashes/transformable_test.rb
115
+ - test/augmented/objects/iffy_test.rb
108
116
  - test/augmented/objects/pickable_test.rb
109
117
  - test/augmented/objects/tackable_test.rb
118
+ - test/augmented/objects/tappable_test.rb
110
119
  - test/augmented/objects/thru_test.rb
111
120
  - test/augmented/procs/chainable_test.rb
112
121
  - test/augmented/symbols/arguable_test.rb