augmented 0.0.1 → 0.1.0

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: 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