augmented 0.2.2 → 0.2.7
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 +4 -4
- data/CHANGELOG.md +20 -0
- data/README.md +161 -27
- data/augmented.gemspec +14 -8
- data/lib/augmented.rb +4 -0
- data/lib/augmented/enumerators/indexing.rb +3 -1
- data/lib/augmented/exceptions.rb +11 -0
- data/lib/augmented/exceptions/chain.rb +16 -0
- data/lib/augmented/exceptions/detailed.rb +22 -0
- data/lib/augmented/exceptions/serializable.rb +25 -0
- data/lib/augmented/objects.rb +2 -0
- data/lib/augmented/objects/in.rb +13 -0
- data/lib/augmented/strings.rb +11 -0
- data/lib/augmented/strings/blank.rb +15 -0
- data/lib/augmented/strings/squish.rb +40 -0
- data/lib/augmented/strings/truncatable.rb +20 -0
- data/lib/augmented/version.rb +1 -1
- metadata +24 -42
- data/test/augmented/arrays/tieable_test.rb +0 -66
- data/test/augmented/enumerators/indexing_test.rb +0 -15
- data/test/augmented/hashes/mappable_test.rb +0 -37
- data/test/augmented/hashes/polymorphable_test.rb +0 -45
- data/test/augmented/hashes/transformable_test.rb +0 -87
- data/test/augmented/modules/refined_test.rb +0 -29
- data/test/augmented/objects/iffy_test.rb +0 -69
- data/test/augmented/objects/pickable_test.rb +0 -39
- data/test/augmented/objects/tackable_test.rb +0 -25
- data/test/augmented/objects/tappable_test.rb +0 -141
- data/test/augmented/objects/thru_test.rb +0 -98
- data/test/augmented/procs/chainable_test.rb +0 -22
- data/test/augmented/procs/rescuable_test.rb +0 -38
- data/test/augmented/symbols/arguable_test.rb +0 -51
- data/test/augmented/symbols/comparing_test.rb +0 -131
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6d65d68527ff708f00861bd8c107acfde5f7ce813ab5a3f6b88a8d9c12a331ad
|
|
4
|
+
data.tar.gz: 2d1c9fe2af451feb5c9eda30aee3514304e4ba62e0baf0d38475a3093389a4d4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 907238de8dda6ab6a1403a43ea31bdc3c7a7315d3c951a62434da1bc91ff932df1111e141ffdef65fd12d7d447c67151d3745e823ba2bbdceeff246f0bea57cf
|
|
7
|
+
data.tar.gz: 8ab148a0c46b387f722041efd2a73aeff7c02e3e939ff1e1edf92c013ab935a08b5c8928bc4becf238f56307e0e7b6099d04b9be64408ba18ed25297577ed21c
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
## [Unreleased]
|
|
2
|
+
|
|
3
|
+
## [0.2.7] - 2021-06-26
|
|
4
|
+
|
|
5
|
+
- Added `String#squish` and `String#squish!`.
|
|
6
|
+
- Added `Object#in?`.
|
|
7
|
+
|
|
8
|
+
## [0.2.6] - 2021-06-23
|
|
9
|
+
|
|
10
|
+
- Fixed `String#blank?` not working on Ruby 2.3.
|
|
11
|
+
|
|
12
|
+
## [0.2.5] - 2021-05-30
|
|
13
|
+
|
|
14
|
+
- Added `Exception#details`, `Exception#details=`, `Exception#detailed`
|
|
15
|
+
- Added `Exception#chain`
|
|
16
|
+
- Added `Exception#to_h`
|
|
17
|
+
|
|
18
|
+
## [0.2.3] - 2021-05-29
|
|
19
|
+
|
|
20
|
+
- Added `String#truncate`, `String#truncate!` and `String#blank?`
|
data/README.md
CHANGED
|
@@ -31,10 +31,12 @@ You can load all refinements for just one type:
|
|
|
31
31
|
```ruby
|
|
32
32
|
using Augmented::Arrays
|
|
33
33
|
using Augmented::Enumerators
|
|
34
|
+
using Augmented::Exceptions
|
|
34
35
|
using Augmented::Hashes
|
|
35
36
|
using Augmented::Modules
|
|
36
37
|
using Augmented::Objects
|
|
37
38
|
using Augmented::Procs
|
|
39
|
+
using Augmented::Strings
|
|
38
40
|
using Augmented::Symbols
|
|
39
41
|
# etc.
|
|
40
42
|
```
|
|
@@ -60,7 +62,7 @@ Weaves an object between the elements of an array. Like `join` but without flatt
|
|
|
60
62
|
```ruby
|
|
61
63
|
using Augmented::Arrays::Tieable
|
|
62
64
|
|
|
63
|
-
[1, 2, 3].tie
|
|
65
|
+
[1, 2, 3].tie(:hello)
|
|
64
66
|
# [1, :hello, 2, :hello, 3]
|
|
65
67
|
|
|
66
68
|
[1, 5, 12].tie{ |a, b| a + b }
|
|
@@ -72,13 +74,88 @@ using Augmented::Arrays::Tieable
|
|
|
72
74
|
|
|
73
75
|
##### `Enumerator#index_by`
|
|
74
76
|
|
|
75
|
-
Builds an index of all elements of an enumerator according to the given criterion.
|
|
77
|
+
Builds an index of all elements of an enumerator according to the given criterion. Last element wins.
|
|
76
78
|
|
|
77
79
|
```ruby
|
|
78
80
|
using Augmented::Enumerators::Indexing
|
|
79
81
|
|
|
80
|
-
['a', 'bb', '
|
|
81
|
-
# {1=>"
|
|
82
|
+
['a', 'bb', 'c', 'ddddd'].to_enum.index_by(&:length)
|
|
83
|
+
# {1=>"c", 2=>"bb", 5=>"ddddd"}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
#### `Augmented::Exceptions`
|
|
88
|
+
|
|
89
|
+
##### `Exception#chain`
|
|
90
|
+
|
|
91
|
+
Returns an enumerator over the exception's causal chain, starting with the exception itself.
|
|
92
|
+
|
|
93
|
+
```ruby
|
|
94
|
+
using Augmented::Exceptions::Chain
|
|
95
|
+
|
|
96
|
+
begin
|
|
97
|
+
begin
|
|
98
|
+
begin
|
|
99
|
+
raise 'first'
|
|
100
|
+
rescue
|
|
101
|
+
raise 'second'
|
|
102
|
+
end
|
|
103
|
+
rescue
|
|
104
|
+
raise 'third'
|
|
105
|
+
end
|
|
106
|
+
rescue => error
|
|
107
|
+
error.chain.map(&:message)
|
|
108
|
+
end
|
|
109
|
+
# ["third", "second", "first"]
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
##### `Exception#details`, `Exception#details=`, `Exception#detailed`
|
|
114
|
+
|
|
115
|
+
Attach a hash of details to any exception.
|
|
116
|
+
|
|
117
|
+
```ruby
|
|
118
|
+
using Augmented::Exceptions::Detailed
|
|
119
|
+
|
|
120
|
+
exception = RuntimeError.new('oops!').detailed(foo: 10, bar: { baz: 30 })
|
|
121
|
+
exception.details
|
|
122
|
+
# {:foo=>10, :bar=>{:baz=>30}}
|
|
123
|
+
exception.details = { bam: 40 }
|
|
124
|
+
exception.details
|
|
125
|
+
# {:bam=>40}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
##### `Exception#to_h`
|
|
130
|
+
|
|
131
|
+
Serializes an exception into a Hash including its backtrace, details and causal chain.
|
|
132
|
+
|
|
133
|
+
```ruby
|
|
134
|
+
using Augmented::Exceptions::Serializable
|
|
135
|
+
using Augmented::Exceptions::Detailed
|
|
136
|
+
|
|
137
|
+
begin
|
|
138
|
+
begin
|
|
139
|
+
raise RuntimeError.new('first').detailed(foo: 10)
|
|
140
|
+
rescue
|
|
141
|
+
raise RuntimeError.new('second').detailed(bar: 20)
|
|
142
|
+
end
|
|
143
|
+
rescue => error
|
|
144
|
+
error.to_h
|
|
145
|
+
end
|
|
146
|
+
# {
|
|
147
|
+
# :class => "RuntimeError",
|
|
148
|
+
# :message => "second",
|
|
149
|
+
# :details => { :bar => 20 },
|
|
150
|
+
# :backtrace => [ ... ],
|
|
151
|
+
# :cause => {
|
|
152
|
+
# :class => "RuntimeError",
|
|
153
|
+
# :message => "first",
|
|
154
|
+
# :details => { :foo => 10 },
|
|
155
|
+
# :backtrace => [ ... ],
|
|
156
|
+
# :cause => nil
|
|
157
|
+
# }
|
|
158
|
+
# }
|
|
82
159
|
```
|
|
83
160
|
|
|
84
161
|
|
|
@@ -149,21 +226,16 @@ tree.transform({ lorem: :upcase, dolor: { sit: triple } })
|
|
|
149
226
|
Makes it less verbose to create small refinements.
|
|
150
227
|
|
|
151
228
|
```ruby
|
|
152
|
-
using Augmented::
|
|
229
|
+
using Augmented::Modules::Refined
|
|
153
230
|
|
|
154
231
|
class TextPage
|
|
155
232
|
using refined String,
|
|
156
|
-
|
|
157
|
-
fill: -> filler { (filler * self.length)[0..length] }
|
|
233
|
+
to_phrase: -> { self.strip.capitalize.gsub(/\.?\z/, '.') }
|
|
158
234
|
|
|
159
235
|
# ...
|
|
160
236
|
|
|
161
237
|
def text
|
|
162
|
-
@
|
|
163
|
-
end
|
|
164
|
-
|
|
165
|
-
def obscured_text
|
|
166
|
-
text.fill '?'
|
|
238
|
+
@lines.map(&:to_phrase).join(' ')
|
|
167
239
|
end
|
|
168
240
|
end
|
|
169
241
|
```
|
|
@@ -178,11 +250,26 @@ Allows you to conditionally return an object, allowing you to be more concise in
|
|
|
178
250
|
```ruby
|
|
179
251
|
using Augmented::Objects::Iffy
|
|
180
252
|
|
|
181
|
-
Person.new.eat
|
|
182
|
-
Person.new.eat
|
|
253
|
+
Person.new.eat(toast.if(toast.buttered?).else(muffin))
|
|
254
|
+
Person.new.eat(toast.if(&:buttered?).else(muffin))
|
|
183
255
|
|
|
184
|
-
Person.new.eat
|
|
185
|
-
Person.new.eat
|
|
256
|
+
Person.new.eat(toast.unless(toast.soggy?).else(muffin))
|
|
257
|
+
Person.new.eat(toast.unless(&:soggy?).else(muffin))
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
##### `Object#in?`
|
|
261
|
+
|
|
262
|
+
Tests if the object is included in a collection (collection must respond to `included?`).
|
|
263
|
+
|
|
264
|
+
```ruby
|
|
265
|
+
using Augmented::Objects::In
|
|
266
|
+
|
|
267
|
+
2.in?([1, 2, 3])
|
|
268
|
+
# true
|
|
269
|
+
5.in?(0..2)
|
|
270
|
+
# false
|
|
271
|
+
'B'.in?('ABC')
|
|
272
|
+
# true
|
|
186
273
|
```
|
|
187
274
|
|
|
188
275
|
##### `Object#pick`
|
|
@@ -193,13 +280,13 @@ Calls a bunch of methods on an object and collects the results.
|
|
|
193
280
|
using Augmented::Objects::Pickable
|
|
194
281
|
|
|
195
282
|
class MyThing
|
|
196
|
-
def
|
|
197
|
-
def
|
|
198
|
-
def
|
|
283
|
+
def foo; 'lorem'; end
|
|
284
|
+
def bar; 'ipsum'; end
|
|
285
|
+
def baz; 'dolor'; end
|
|
199
286
|
end
|
|
200
287
|
|
|
201
|
-
MyThing.new.pick
|
|
202
|
-
# {:
|
|
288
|
+
MyThing.new.pick(:foo, :baz)
|
|
289
|
+
# {:foo=>"lorem", :baz=>"dolor"}
|
|
203
290
|
```
|
|
204
291
|
|
|
205
292
|
##### `Object#tack`
|
|
@@ -209,8 +296,8 @@ Appends a bunch of singleton methods to an object.
|
|
|
209
296
|
```ruby
|
|
210
297
|
using Augmented::Objects::Tackable
|
|
211
298
|
|
|
212
|
-
Object.new.tack(
|
|
213
|
-
# hello I'm
|
|
299
|
+
Object.new.tack(name: 'Alice', greet: -> { puts "hello I'm #{name}" }).greet
|
|
300
|
+
# hello I'm Alice
|
|
214
301
|
```
|
|
215
302
|
|
|
216
303
|
##### `Object#tap_if`, `Object#tap_unless`
|
|
@@ -269,13 +356,60 @@ Wraps a `Proc` to rescue it from certain exceptions while returning a given valu
|
|
|
269
356
|
```ruby
|
|
270
357
|
using Augmented::Procs::Rescuable
|
|
271
358
|
|
|
272
|
-
integerify = proc{ |x| Integer(x) }.rescues
|
|
359
|
+
integerify = proc{ |x| Integer(x) }.rescues(ArgumentError, 42)
|
|
273
360
|
|
|
274
|
-
['1', '2', '
|
|
361
|
+
['1', '2', 'oops!', '4'].map(&integerify)
|
|
275
362
|
# [1, 2, 42, 4]
|
|
276
363
|
```
|
|
277
364
|
|
|
278
365
|
|
|
366
|
+
#### `Augmented::Strings`
|
|
367
|
+
|
|
368
|
+
##### `String#blank?`
|
|
369
|
+
|
|
370
|
+
Tests if a string is empty or made of whitespace.
|
|
371
|
+
|
|
372
|
+
```ruby
|
|
373
|
+
using Augmented::Strings::Blank
|
|
374
|
+
|
|
375
|
+
''.blank?
|
|
376
|
+
# true
|
|
377
|
+
' '.blank?
|
|
378
|
+
# true
|
|
379
|
+
' hello '.blank?
|
|
380
|
+
# false
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
##### `String#squish`, `String#squish!`
|
|
385
|
+
|
|
386
|
+
Replaces runs of whitespace with a single space except at the edges of the string. Can be given a custom pattern and replacement.
|
|
387
|
+
|
|
388
|
+
```ruby
|
|
389
|
+
using Augmented::Strings::Squish
|
|
390
|
+
|
|
391
|
+
' hello world '.squish!
|
|
392
|
+
# "hello world"
|
|
393
|
+
|
|
394
|
+
'---what-a-nice--kebab-'.squish(/\W+/, '_')
|
|
395
|
+
# "what_a_nice_kebab"
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
##### `String#truncate`, `String#truncate!`
|
|
400
|
+
|
|
401
|
+
Returns a prefix of a string up to a given number of characters.
|
|
402
|
+
|
|
403
|
+
```ruby
|
|
404
|
+
using Augmented::Strings::Truncatable
|
|
405
|
+
|
|
406
|
+
'hello world'.truncate(5)
|
|
407
|
+
# "hello"
|
|
408
|
+
[(string = 'hello world'), string.truncate!(5)]
|
|
409
|
+
# ["hello", "hello"]
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
|
|
279
413
|
#### `Augmented::Symbols`
|
|
280
414
|
|
|
281
415
|
##### `Symbol#with`
|
|
@@ -311,8 +445,8 @@ end
|
|
|
311
445
|
|
|
312
446
|
users = [ User.new('Marianne'), User.new('Jeremy') ]
|
|
313
447
|
|
|
314
|
-
users.find
|
|
315
|
-
# <User:0x... name='Marianne'>
|
|
448
|
+
users.find(&:name.eq('Marianne'))
|
|
449
|
+
# <User:0x... @name='Marianne'>
|
|
316
450
|
```
|
|
317
451
|
|
|
318
452
|
|
data/augmented.gemspec
CHANGED
|
@@ -6,18 +6,24 @@ require 'augmented/version'
|
|
|
6
6
|
Gem::Specification.new do |spec|
|
|
7
7
|
spec.name = "augmented"
|
|
8
8
|
spec.version = Augmented::VERSION
|
|
9
|
-
spec.authors = ["
|
|
10
|
-
spec.email = ["bruno@brunze.com"]
|
|
9
|
+
spec.authors = ["brunze"]
|
|
11
10
|
spec.summary = %q{Useful extra methods for some Ruby core types.}
|
|
12
11
|
spec.description = %q{Adds a few useful extra methods to some of Ruby's core types, available as refinements.}
|
|
13
12
|
spec.homepage = "https://github.com/brunze/augmented"
|
|
14
13
|
spec.license = "MIT"
|
|
15
14
|
|
|
16
|
-
spec.
|
|
17
|
-
spec.
|
|
18
|
-
spec.
|
|
19
|
-
spec.require_paths = ["lib"]
|
|
15
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
|
16
|
+
spec.metadata['source_code_uri'] = spec.homepage
|
|
17
|
+
spec.metadata['changelog_uri'] = spec.homepage + '/CHANGELOG.md'
|
|
20
18
|
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
# Specify which files should be added to the gem when it is released.
|
|
20
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
|
21
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
|
22
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
|
|
23
|
+
end
|
|
24
|
+
spec.bindir = 'bin'
|
|
25
|
+
spec.require_paths = ['lib']
|
|
26
|
+
|
|
27
|
+
spec.add_development_dependency "bundler", "~> 2"
|
|
28
|
+
spec.add_development_dependency "rake", ">= 13.0.3"
|
|
23
29
|
end
|
data/lib/augmented.rb
CHANGED
|
@@ -2,18 +2,22 @@ require 'augmented/version'
|
|
|
2
2
|
|
|
3
3
|
require 'augmented/arrays'
|
|
4
4
|
require 'augmented/enumerators'
|
|
5
|
+
require 'augmented/exceptions'
|
|
5
6
|
require 'augmented/hashes'
|
|
6
7
|
require 'augmented/modules'
|
|
7
8
|
require 'augmented/objects'
|
|
8
9
|
require 'augmented/procs'
|
|
10
|
+
require 'augmented/strings'
|
|
9
11
|
require 'augmented/symbols'
|
|
10
12
|
|
|
11
13
|
module Augmented
|
|
12
14
|
include Arrays
|
|
13
15
|
include Enumerators
|
|
16
|
+
include Exceptions
|
|
14
17
|
include Hashes
|
|
15
18
|
include Modules
|
|
16
19
|
include Objects
|
|
17
20
|
include Procs
|
|
21
|
+
include Strings
|
|
18
22
|
include Symbols
|
|
19
23
|
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module Augmented
|
|
2
|
+
module Exceptions
|
|
3
|
+
module Chain
|
|
4
|
+
refine Exception do
|
|
5
|
+
|
|
6
|
+
def chain
|
|
7
|
+
Enumerator.new do |yielder|
|
|
8
|
+
yielder << exception = self
|
|
9
|
+
yielder << exception while exception = exception.cause
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module Augmented
|
|
2
|
+
module Exceptions
|
|
3
|
+
module Detailed
|
|
4
|
+
refine Exception do
|
|
5
|
+
|
|
6
|
+
def details
|
|
7
|
+
@_details ||= {}
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def details= **details
|
|
11
|
+
@_details = details
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def detailed **details
|
|
15
|
+
self.details = details
|
|
16
|
+
self
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module Augmented
|
|
2
|
+
module Exceptions
|
|
3
|
+
module Serializable
|
|
4
|
+
refine Exception do
|
|
5
|
+
using Chain
|
|
6
|
+
using Detailed
|
|
7
|
+
|
|
8
|
+
def to_h
|
|
9
|
+
self.chain.map do |exception|
|
|
10
|
+
{
|
|
11
|
+
class: exception.class.name,
|
|
12
|
+
message: exception.message,
|
|
13
|
+
details: exception.details,
|
|
14
|
+
backtrace: exception.backtrace || [],
|
|
15
|
+
cause: nil,
|
|
16
|
+
}
|
|
17
|
+
end.reverse.reduce do |cause, exception|
|
|
18
|
+
exception.merge!(cause: cause)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|