refinements 7.4.0 → 7.9.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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/README.adoc +427 -103
- data/lib/refinements.rb +1 -0
- data/lib/refinements/arrays.rb +8 -0
- data/lib/refinements/files.rb +1 -0
- data/lib/refinements/hashes.rb +37 -8
- data/lib/refinements/identity.rb +1 -1
- data/lib/refinements/pathnames.rb +24 -6
- data/lib/refinements/string_ios.rb +13 -0
- data/lib/refinements/strings.rb +22 -27
- metadata +17 -16
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ba7c2934d38986ae19d3a41bdc1305164ebe2355bb30afa925eebbeb9746f962
|
4
|
+
data.tar.gz: 1945d2226c6ca304aa9958635aab6a87880b66e43566691c3ab509f5b2e77f6b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 34e601f3bfe0ebe6b35ddf54dea67ef9c33d7436fae5103a2ce03106a34026f1920a6f06369ba2516ceb0a550bb6868fcd5491084cca5b6dd20ed746b4772a39
|
7
|
+
data.tar.gz: 8e4d5de5f29f28df044333dbaa34fb0a6d9b34911e3e911bd5593caf4dfeb52c0c0767f5a01d164542c54a4d936453b14f6131c055234a5911d73c80673c7d14
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/README.adoc
CHANGED
@@ -15,62 +15,22 @@ toc::[]
|
|
15
15
|
|
16
16
|
== Features
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
*
|
23
|
-
|
24
|
-
*
|
25
|
-
|
26
|
-
*
|
27
|
-
|
28
|
-
file for manipulation and immediate writing back to the same file.
|
29
|
-
* *Hashes*:
|
30
|
-
** `#except` - Answers new hash with given keys removed without modifying calling hash.
|
31
|
-
** `#except!` - Answers new hash with given keys removed while modifying calling hash.
|
32
|
-
** `#symbolize_keys` - Converts keys to symbols without modifying itself.
|
33
|
-
** `#symbolize_keys!` - Converts keys to symbols while modifying itself.
|
34
|
-
** `#deep_merge` - Merges deeply nested hashes together without modifying itself.
|
35
|
-
** `#deep_merge!` - Merges deeply nested hashes together while modifying itself.
|
36
|
-
** `#deep_symbolize_keys` - Symbolizes keys of nested hash without modifying itself. Does not handle
|
37
|
-
nested arrays, though.
|
38
|
-
** `#deep_symbolize_keys!` - Symbolizes keys of nested hash while modifying itself. Does not handle
|
39
|
-
nested arrays, though.
|
40
|
-
** `#recurse` - Applies block to nested hash. Does not handle nested arrays, though.
|
41
|
-
** `#rekey` - Transforms keys per mapping (size of mapping can vary).
|
42
|
-
** `#reverse_merge` - Merges calling hash into passed in hash without modifying calling hash.
|
43
|
-
** `#reverse_merge!` - Merges calling hash into passed in hash while modifying calling hash.
|
44
|
-
** `#use` - Passes each hash value as a block argument for further processing.
|
45
|
-
* *Pathnames*:
|
46
|
-
** `#name` - Answers file name without extension.
|
47
|
-
** `#copy` - Copies file from current location to new location.
|
48
|
-
** `#directories` - Answers all or filtered directories for current path.
|
49
|
-
** `#extensions` - Answers file extensions as an array.
|
50
|
-
** `#files` - Answers all or filtered files for current path.
|
51
|
-
** `#relative_parent_from` - Answers relative path from parent directory. This is a complement to
|
52
|
-
`#relative_path_from`.
|
53
|
-
** `#make_ancestors` - Ensures all ancestor directories are created for a path.
|
54
|
-
** `#rewrite` - When given a block, it provides the contents of the recently read file for
|
55
|
-
manipulation and immediate writing back to the same file.
|
56
|
-
** `#touch` - Updates access and modification times to current time for path.
|
57
|
-
* *Strings*:
|
58
|
-
** `#first` - Answers first character of a string or first set of characters if given a number.
|
59
|
-
** `#last` - Answers last character of a string or last set of characters if given a number.
|
60
|
-
** `#blank?` - Answers `true`/`false` based on whether string is blank or not
|
61
|
-
(i.e. `<space>`, `\n`, `\t`, `\r`).
|
62
|
-
** `#up` - Answers string with only first letter upcased.
|
63
|
-
** `#down` - Answers string with only first letter downcased.
|
64
|
-
** `#camelcase` - Answers a camelcased string.
|
65
|
-
** `#snakecase` - Answers a snakecased string.
|
66
|
-
** `#titleize` - Answers titleized string.
|
67
|
-
** `#to_bool` - Answers string as a boolean.
|
18
|
+
Enhances the following objects:
|
19
|
+
|
20
|
+
* Array
|
21
|
+
* BigDecimal
|
22
|
+
* DateTime
|
23
|
+
* File
|
24
|
+
* Hash
|
25
|
+
* Pathname
|
26
|
+
* String
|
27
|
+
* StringIO
|
68
28
|
|
69
29
|
== Requirements
|
70
30
|
|
71
|
-
. https://www.ruby-lang.org[Ruby
|
72
|
-
. A solid understanding of https://www.
|
73
|
-
scope].
|
31
|
+
. https://www.ruby-lang.org[Ruby].
|
32
|
+
. A solid understanding of link:https://www.alchemists.io/articles/ruby_refinements[Ruby refinements
|
33
|
+
and lexical scope].
|
74
34
|
|
75
35
|
== Setup
|
76
36
|
|
@@ -130,6 +90,7 @@ require "refinements/files"
|
|
130
90
|
require "refinements/hashes"
|
131
91
|
require "refinements/pathnames"
|
132
92
|
require "refinements/strings"
|
93
|
+
require "refinements/string_ios"
|
133
94
|
----
|
134
95
|
|
135
96
|
=== Using
|
@@ -146,6 +107,7 @@ class Example
|
|
146
107
|
using Refinements::Hashes
|
147
108
|
using Refinements::Pathnames
|
148
109
|
using Refinements::Strings
|
110
|
+
using Refinements::StringIOs
|
149
111
|
end
|
150
112
|
----
|
151
113
|
|
@@ -155,19 +117,58 @@ The following sections demonstrate how each refinement enriches your objects wit
|
|
155
117
|
|
156
118
|
==== Array
|
157
119
|
|
120
|
+
===== #compress
|
121
|
+
|
122
|
+
Removes `nil` and empty values without modifying itself.
|
123
|
+
|
158
124
|
[source,ruby]
|
159
125
|
----
|
160
126
|
example = ["An", nil, "", "Example"]
|
161
|
-
example.compress
|
162
|
-
example
|
127
|
+
example.compress # => ["An", "Example"]
|
128
|
+
example # => ["An", nil, "", "Example"]
|
129
|
+
----
|
130
|
+
|
131
|
+
===== #compress!
|
163
132
|
|
133
|
+
Removes `nil` and empty values while modifying itself.
|
134
|
+
|
135
|
+
[source,ruby]
|
136
|
+
----
|
164
137
|
example = ["An", nil, "", "Example"]
|
165
|
-
example.compress!
|
166
|
-
example
|
138
|
+
example.compress! # => ["An", "Example"]
|
139
|
+
example # => ["An", "Example"]
|
140
|
+
----
|
141
|
+
|
142
|
+
===== #include
|
143
|
+
|
144
|
+
Adds given array or elements without modifying itself.
|
145
|
+
|
146
|
+
[source,ruby]
|
147
|
+
----
|
148
|
+
[1, 2, 3].include [4, 5] # => [1, 2, 3, 4, 5]
|
149
|
+
[1, 2, 3].include 4, 5 # => [1, 2, 3, 4, 5]
|
150
|
+
----
|
151
|
+
|
152
|
+
===== #exclude
|
153
|
+
|
154
|
+
Removes given array or elements without modifying itself.
|
155
|
+
|
156
|
+
[source,ruby]
|
157
|
+
----
|
158
|
+
[1, 2, 3, 4, 5].exclude [4, 5] # => [1, 2, 3]
|
159
|
+
[1, 2, 3, 4, 5].exclude 4, 5 # => [1, 2, 3]
|
160
|
+
----
|
161
|
+
|
162
|
+
===== #ring
|
167
163
|
|
164
|
+
Answers a circular array which can enumerate before, current, after elements.
|
165
|
+
|
166
|
+
[source,ruby]
|
167
|
+
----
|
168
168
|
example = [1, 2, 3]
|
169
169
|
example.ring # => #<Enumerator: ...>
|
170
170
|
example.ring { |(before, current, after)| puts "#{before} #{current} #{after}" }
|
171
|
+
|
171
172
|
# [3 1 2]
|
172
173
|
# [1 2 3]
|
173
174
|
# [2 3 1]
|
@@ -175,6 +176,10 @@ example.ring { |(before, current, after)| puts "#{before} #{current} #{after}" }
|
|
175
176
|
|
176
177
|
==== Big Decimal
|
177
178
|
|
179
|
+
===== #inspect
|
180
|
+
|
181
|
+
Allows one to inspect a big decimal with numeric representation.
|
182
|
+
|
178
183
|
[source,ruby]
|
179
184
|
----
|
180
185
|
BigDecimal.new("5.0E-10").inspect # => "#<BigDecimal:3fd3d458fe84 0.0000000005>"
|
@@ -182,6 +187,10 @@ BigDecimal.new("5.0E-10").inspect # => "#<BigDecimal:3fd3d458fe84 0.0000000005>"
|
|
182
187
|
|
183
188
|
==== DateTime
|
184
189
|
|
190
|
+
===== .utc
|
191
|
+
|
192
|
+
Answers new DateTime object for current UTC date/time.
|
193
|
+
|
185
194
|
[source,ruby]
|
186
195
|
----
|
187
196
|
DateTime.utc # => #<DateTime: 2019-12-31T18:17:00+00:00 ((2458849j,65820s,181867000n),+0s,2299161j)>
|
@@ -189,6 +198,11 @@ DateTime.utc # => #<DateTime: 2019-12-31T18:17:00+00:00 ((2458849j,65820s,181867
|
|
189
198
|
|
190
199
|
==== File
|
191
200
|
|
201
|
+
===== .rewrite
|
202
|
+
|
203
|
+
When given a file path and a block, it provides the contents of the recently read file for
|
204
|
+
manipulation and immediate writing back to the same file.
|
205
|
+
|
192
206
|
[source,ruby]
|
193
207
|
----
|
194
208
|
File.rewrite("/test.txt") { |content| content.gsub "[placeholder]", "example" }
|
@@ -196,122 +210,432 @@ File.rewrite("/test.txt") { |content| content.gsub "[placeholder]", "example" }
|
|
196
210
|
|
197
211
|
==== Hash
|
198
212
|
|
213
|
+
===== .infinite
|
214
|
+
|
215
|
+
Answers new hash where missing keys, even deeply nested, answer an empty hash.
|
216
|
+
|
217
|
+
[source,ruby]
|
218
|
+
----
|
219
|
+
example = Hash.infinite
|
220
|
+
example[:a] # => {}
|
221
|
+
example[:a][:b][:c] # => {}
|
222
|
+
----
|
223
|
+
|
224
|
+
===== .with_default
|
225
|
+
|
226
|
+
Answers new hash where every top-level missing key has the same default value.
|
227
|
+
|
228
|
+
[source,ruby]
|
229
|
+
----
|
230
|
+
example = Hash.with_default ""
|
231
|
+
example[:a] # => ""
|
232
|
+
|
233
|
+
example = Hash.with_default []
|
234
|
+
example[:b] # => []
|
235
|
+
----
|
236
|
+
|
237
|
+
===== #except
|
238
|
+
|
239
|
+
Answers new hash with given keys removed without modifying itself.
|
240
|
+
|
199
241
|
[source,ruby]
|
200
242
|
----
|
201
243
|
example = {a: 1, b: 2, c: 3}
|
202
|
-
example.except :a, :b
|
203
|
-
example
|
244
|
+
example.except :a, :b # => {c: 3}
|
245
|
+
example # => {a: 1, b: 2, c: 3}
|
246
|
+
----
|
247
|
+
|
248
|
+
===== #except!
|
249
|
+
|
250
|
+
Answers new hash with given keys removed while modifying itself.
|
204
251
|
|
252
|
+
[source,ruby]
|
253
|
+
----
|
205
254
|
example = {a: 1, b: 2, c: 3}
|
206
|
-
example.except! :a, :b
|
207
|
-
example
|
255
|
+
example.except! :a, :b # => {c: 3}
|
256
|
+
example # => {c: 3}
|
257
|
+
----
|
258
|
+
|
259
|
+
===== #flatten_keys
|
260
|
+
|
261
|
+
Flattens nested keys as top-level keys without modifying itself. Does not handle nested arrays,
|
262
|
+
though.
|
263
|
+
|
264
|
+
[source,ruby]
|
265
|
+
----
|
266
|
+
{a: {b: 1}}.flatten_keys prefix: :test # => {test_a_b: 1}
|
267
|
+
{a: {b: 1}}.flatten_keys delimiter: :| # => {:"a|b" => 1}
|
268
|
+
|
269
|
+
{a: {b: 1}}.flatten_keys cast: :to_s # => {"a_b" => 1}
|
270
|
+
{"a" => {"b" => 1}}.flatten_keys cast: :to_sym # => {a_b: 1}
|
271
|
+
|
272
|
+
example = {a: {b: 1}}
|
273
|
+
example.flatten_keys # => {a_b: 1}
|
274
|
+
example # => {a: {b: 1}}
|
275
|
+
----
|
208
276
|
|
277
|
+
===== #flatten_keys!
|
278
|
+
|
279
|
+
Flattens nested keys as top-level keys while modifying itself. Does not handle nested arrays,
|
280
|
+
though.
|
281
|
+
|
282
|
+
[source,ruby]
|
283
|
+
----
|
284
|
+
example = {a: {b: 1}}
|
285
|
+
example.flatten_keys! # => {a_b: 1}
|
286
|
+
example # => {a_b: 1}
|
287
|
+
----
|
288
|
+
|
289
|
+
===== #symbolize_keys
|
290
|
+
|
291
|
+
Converts keys to symbols without modifying itself.
|
292
|
+
|
293
|
+
[source,ruby]
|
294
|
+
----
|
209
295
|
example = {"a" => 1, "b" => 2}
|
210
|
-
example.symbolize_keys
|
211
|
-
example
|
296
|
+
example.symbolize_keys # => {a: 1, b: 2}
|
297
|
+
example # => {"a" => 1, "b" => 2}
|
298
|
+
----
|
212
299
|
|
300
|
+
===== #symbolize_keys!
|
301
|
+
|
302
|
+
Converts keys to symbols while modifying itself.
|
303
|
+
|
304
|
+
[source,ruby]
|
305
|
+
----
|
213
306
|
example = {"a" => 1, "b" => 2}
|
214
|
-
example.symbolize_keys!
|
215
|
-
example
|
307
|
+
example.symbolize_keys! # => {a: 1, b: 2}
|
308
|
+
example # => {a: 1, b: 2}
|
309
|
+
----
|
216
310
|
|
217
|
-
|
218
|
-
example.slice :a, :c # => {a: 1, c: 3}
|
219
|
-
example # => {a: 1, b: 2, c: 3}
|
311
|
+
===== #deep_merge
|
220
312
|
|
221
|
-
|
222
|
-
example.slice! :a, :c # => {a: 1, c: 3}
|
223
|
-
example # => {a: 1, c: 3}
|
313
|
+
Merges deeply nested hashes together without modifying itself.
|
224
314
|
|
315
|
+
[source,ruby]
|
316
|
+
----
|
225
317
|
example = {a: "A", b: {one: "One", two: "Two"}}
|
226
|
-
example.deep_merge b: {one: 1}
|
227
|
-
example
|
318
|
+
example.deep_merge b: {one: 1} # => {a: "A", b: {one: 1, two: "Two"}}
|
319
|
+
example # => {a: "A", b: {one: "One", two: "Two"}}
|
320
|
+
----
|
321
|
+
|
322
|
+
===== #deep_merge!
|
323
|
+
|
324
|
+
Merges deeply nested hashes together while modifying itself.
|
228
325
|
|
326
|
+
[source,ruby]
|
327
|
+
----
|
229
328
|
example = {a: "A", b: {one: "One", two: "Two"}}
|
230
|
-
example.deep_merge! b: {one: 1}
|
231
|
-
example
|
329
|
+
example.deep_merge! b: {one: 1} # => {a: "A", b: {one: 1, two: "Two"}}
|
330
|
+
example # => {a: "A", b: {one: 1, two: "Two"}}
|
331
|
+
----
|
232
332
|
|
333
|
+
===== #deep_symbolize_keys
|
334
|
+
|
335
|
+
Symbolizes keys of nested hash without modifying itself. Does not handle nested arrays, though.
|
336
|
+
|
337
|
+
[source,ruby]
|
338
|
+
----
|
233
339
|
example = {"a" => {"b" => 2}}
|
234
|
-
example.deep_symbolize_keys
|
235
|
-
example
|
340
|
+
example.deep_symbolize_keys # => {a: {b: 1}}
|
341
|
+
example # => {"a" => {"b" => 2}}
|
342
|
+
----
|
343
|
+
|
344
|
+
===== #deep_symbolize_keys!
|
236
345
|
|
346
|
+
Symbolizes keys of nested hash while modifying itself. Does not handle nested arrays, though.
|
347
|
+
|
348
|
+
[source,ruby]
|
349
|
+
----
|
237
350
|
example = {"a" => {"b" => 2}}
|
238
|
-
example.deep_symbolize_keys!
|
239
|
-
example
|
351
|
+
example.deep_symbolize_keys! # => {a: {b: 1}}
|
352
|
+
example # => {a: {b: 1}}
|
353
|
+
----
|
354
|
+
|
355
|
+
===== #recurse
|
356
|
+
|
357
|
+
Applies block to nested hash. Does not handle nested arrays, though.
|
240
358
|
|
359
|
+
[source,ruby]
|
360
|
+
----
|
241
361
|
example = {"a" => {"b" => 1}}
|
242
|
-
example.recurse(&:symbolize_keys)
|
243
|
-
example.recurse(&:invert)
|
362
|
+
example.recurse(&:symbolize_keys) # => {a: {b: 1}}
|
363
|
+
example.recurse(&:invert) # => {{"b" => 1} => "a"}
|
364
|
+
----
|
244
365
|
|
366
|
+
===== #rekey
|
367
|
+
|
368
|
+
Transforms keys per mapping (size of mapping can vary) without modifying itself.
|
369
|
+
|
370
|
+
[source,ruby]
|
371
|
+
----
|
372
|
+
example = {a: 1, b: 2, c: 3}
|
373
|
+
example.rekey a: :amber, b: :blue # => {amber: 1, blue: 2, c: 3}
|
374
|
+
example # => {a: 1, b: 2, c: 3}
|
375
|
+
----
|
376
|
+
|
377
|
+
===== #rekey!
|
378
|
+
|
379
|
+
Transforms keys per mapping (size of mapping can vary) while modifying itself.
|
380
|
+
|
381
|
+
[source,ruby]
|
382
|
+
----
|
245
383
|
example = {a: 1, b: 2, c: 3}
|
246
|
-
example.rekey a: :amber, b: :blue
|
384
|
+
example.rekey! a: :amber, b: :blue # => {amber: 1, blue: 2, c: 3}
|
385
|
+
example # => {amber: 1, blue: 2, c: 3}
|
386
|
+
----
|
387
|
+
|
388
|
+
===== #reverse_merge
|
389
|
+
|
390
|
+
Merges calling hash into passed in hash without modifying itself.
|
247
391
|
|
392
|
+
[source,ruby]
|
393
|
+
----
|
248
394
|
example = {a: 1, b: 2}
|
249
|
-
example.reverse_merge a: 0, c: 3
|
250
|
-
example
|
395
|
+
example.reverse_merge a: 0, c: 3 # => {a: 1, b: 2, c: 3}
|
396
|
+
example # => {a: 1, b: 2}
|
397
|
+
----
|
398
|
+
|
399
|
+
===== #reverse_merge!
|
251
400
|
|
401
|
+
Merges calling hash into passed in hash while modifying itself.
|
402
|
+
|
403
|
+
[source,ruby]
|
404
|
+
----
|
252
405
|
example = {a: 1, b: 2}
|
253
|
-
example.reverse_merge! a: 0, c: 3
|
254
|
-
example
|
406
|
+
example.reverse_merge! a: 0, c: 3 # => {a: 1, b: 2, c: 3}
|
407
|
+
example # => {a: 1, b: 2, c: 3}
|
408
|
+
----
|
255
409
|
|
410
|
+
===== #use
|
411
|
+
|
412
|
+
Passes each hash value as a block argument for further processing.
|
413
|
+
|
414
|
+
[source,ruby]
|
415
|
+
----
|
256
416
|
example = {unit: "221B", street: "Baker Street", city: "London", country: "UK"}
|
257
417
|
example.use { |unit, street| "#{unit} #{street}" } # => "221B Baker Street"
|
258
418
|
----
|
259
419
|
|
260
420
|
==== Pathname
|
261
421
|
|
422
|
+
===== Pathname
|
423
|
+
|
424
|
+
Conversion function (refined from `Kernel`) which can cast `nil` into a pathname.
|
425
|
+
|
426
|
+
[source,ruby]
|
427
|
+
----
|
428
|
+
Pathname(nil) # => Pathname("")
|
429
|
+
----
|
430
|
+
|
431
|
+
===== #name
|
432
|
+
|
433
|
+
Answers file name without extension.
|
434
|
+
|
262
435
|
[source,ruby]
|
263
436
|
----
|
264
437
|
Pathname("example.txt").name # => Pathname("example")
|
438
|
+
----
|
439
|
+
|
440
|
+
===== #copy
|
441
|
+
|
442
|
+
Copies file from current location to new location.
|
265
443
|
|
444
|
+
[source,ruby]
|
445
|
+
----
|
266
446
|
Pathname("input.txt").copy Pathname("output.txt")
|
447
|
+
----
|
448
|
+
|
449
|
+
===== #directories
|
267
450
|
|
268
|
-
|
269
|
-
Pathname("/example").directories "a*" # => [Pathname("a")]
|
451
|
+
Answers all or filtered directories for current path.
|
270
452
|
|
453
|
+
[source,ruby]
|
454
|
+
----
|
455
|
+
Pathname("/example").directories # => [Pathname("a"), Pathname("b")]
|
456
|
+
Pathname("/example").directories "a*" # => [Pathname("a")]
|
457
|
+
Pathname("/example").directories flag: File::FNM_DOTMATCH # => [Pathname(".."), Pathname(".")]
|
458
|
+
----
|
459
|
+
|
460
|
+
===== #extensions
|
461
|
+
|
462
|
+
Answers file extensions as an array.
|
463
|
+
|
464
|
+
[source,ruby]
|
465
|
+
----
|
271
466
|
Pathname("example.txt.erb").extensions # => [".txt", ".erb"]
|
467
|
+
----
|
272
468
|
|
273
|
-
|
274
|
-
Pathname("/example").files "*.png" # => [Pathname("a.png")]
|
469
|
+
===== #files
|
275
470
|
|
276
|
-
|
471
|
+
Answers all or filtered files for current path.
|
472
|
+
|
473
|
+
[source,ruby]
|
474
|
+
----
|
475
|
+
Pathname("/example").files # => [Pathname("a.txt"), Pathname("a.png")]
|
476
|
+
Pathname("/example").files "*.png" # => [Pathname("a.png")]
|
477
|
+
Pathname("/example").files flag: File::FNM_DOTMATCH # => [Pathname(".ruby-version")]
|
478
|
+
----
|
479
|
+
|
480
|
+
===== #gsub
|
481
|
+
|
482
|
+
Same behavior as `String#gsub` but answers a path with patterns replaced with desired substitutes.
|
483
|
+
|
484
|
+
[source,ruby]
|
485
|
+
----
|
486
|
+
Pathname("/a/path/some/path").gsub("path", "test")
|
487
|
+
# => Pathname("/a/test/some/test")
|
277
488
|
|
489
|
+
Pathname("/%placeholder%/some/%placeholder%").gsub("%placeholder%", "test")
|
490
|
+
# => Pathname("/test/some/test")
|
491
|
+
----
|
492
|
+
|
493
|
+
===== #relative_parent
|
494
|
+
|
495
|
+
Answers relative path from parent directory. This is a complement to `#relative_path_from`.
|
496
|
+
|
497
|
+
[source,ruby]
|
498
|
+
----
|
499
|
+
Pathname("/one/two/three").relative_parent("/one") # => Pathname "two"
|
500
|
+
----
|
501
|
+
|
502
|
+
===== #make_ancestors
|
503
|
+
|
504
|
+
Ensures all ancestor directories are created for a path.
|
505
|
+
|
506
|
+
[source,ruby]
|
507
|
+
----
|
278
508
|
Pathname("/one/two").make_ancestors
|
279
|
-
Pathname("/one").exist?
|
280
|
-
Pathname("/one/two").exist?
|
509
|
+
Pathname("/one").exist? # => true
|
510
|
+
Pathname("/one/two").exist? # => false
|
511
|
+
----
|
512
|
+
|
513
|
+
===== #rewrite
|
281
514
|
|
515
|
+
When given a block, it provides the contents of the recently read file for manipulation and
|
516
|
+
immediate writing back to the same file.
|
517
|
+
|
518
|
+
[source,ruby]
|
519
|
+
----
|
282
520
|
Pathname("/test.txt").rewrite { |content| content.sub "[placeholder]", "example" }
|
521
|
+
----
|
283
522
|
|
523
|
+
===== #touch
|
524
|
+
|
525
|
+
Updates access and modification times for path. Defaults to current time.
|
526
|
+
|
527
|
+
[source,ruby]
|
528
|
+
----
|
284
529
|
Pathname("example.txt").touch
|
285
|
-
Pathname("example.txt").touch
|
530
|
+
Pathname("example.txt").touch at: Time.now - 1
|
286
531
|
----
|
287
532
|
|
288
533
|
==== String
|
289
534
|
|
535
|
+
===== #first
|
536
|
+
|
537
|
+
Answers first character of a string or first set of characters if given a number.
|
538
|
+
|
539
|
+
[source,ruby]
|
540
|
+
----
|
541
|
+
"example".first # => "e"
|
542
|
+
"example".first 4 # => "exam"
|
543
|
+
----
|
544
|
+
|
545
|
+
===== #last
|
546
|
+
|
547
|
+
Answers last character of a string or last set of characters if given a number.
|
548
|
+
|
290
549
|
[source,ruby]
|
291
550
|
----
|
292
|
-
"
|
293
|
-
"
|
551
|
+
"instant".last # => "t"
|
552
|
+
"instant".last 3 # => "ant"
|
553
|
+
----
|
294
554
|
|
295
|
-
|
296
|
-
"instant".last 3 # => "ant"
|
555
|
+
===== #blank?
|
297
556
|
|
557
|
+
Answers `true`/`false` based on whether string is blank, `<space>`, `\n`, `\t`, and/or `\r`.
|
558
|
+
|
559
|
+
[source,ruby]
|
560
|
+
----
|
298
561
|
" \n\t\r".blank? # => true
|
562
|
+
----
|
563
|
+
|
564
|
+
===== #up
|
565
|
+
|
566
|
+
Answers string with only first letter upcased.
|
299
567
|
|
568
|
+
[source,ruby]
|
569
|
+
----
|
300
570
|
"example".up # => "Example"
|
571
|
+
----
|
572
|
+
|
573
|
+
===== #down
|
301
574
|
|
575
|
+
Answers string with only first letter downcased.
|
576
|
+
|
577
|
+
[source,ruby]
|
578
|
+
----
|
302
579
|
"EXAMPLE".down # => "eXAMPLE"
|
580
|
+
----
|
581
|
+
|
582
|
+
===== #camelcase
|
303
583
|
|
584
|
+
Answers a camelcased string.
|
585
|
+
|
586
|
+
[source,ruby]
|
587
|
+
----
|
304
588
|
"this_is_an_example".camelcase # => "ThisIsAnExample"
|
589
|
+
----
|
590
|
+
|
591
|
+
===== #snakecase
|
592
|
+
|
593
|
+
Answers a snakecased string.
|
305
594
|
|
595
|
+
[source,ruby]
|
596
|
+
----
|
306
597
|
"ThisIsAnExample".snakecase # => "this_is_an_example"
|
598
|
+
----
|
599
|
+
|
600
|
+
===== #titleize
|
307
601
|
|
602
|
+
Answers titleized string.
|
603
|
+
|
604
|
+
[source,ruby]
|
605
|
+
----
|
308
606
|
"ThisIsAnExample".titleize # => "This Is An Example"
|
607
|
+
----
|
608
|
+
|
609
|
+
===== #to_bool
|
610
|
+
|
611
|
+
Answers string as a boolean.
|
612
|
+
|
613
|
+
[source,ruby]
|
614
|
+
----
|
615
|
+
"true".to_bool # => true
|
616
|
+
"yes".to_bool # => true
|
617
|
+
"1".to_bool # => true
|
618
|
+
"".to_bool # => false
|
619
|
+
"example".to_bool # => false
|
620
|
+
----
|
621
|
+
|
622
|
+
==== String IO
|
623
|
+
|
624
|
+
===== #reread
|
625
|
+
|
626
|
+
Answers full string by rewinding to beginning of string and reading all content.
|
627
|
+
|
628
|
+
[source,ruby]
|
629
|
+
----
|
630
|
+
io = StringIO.new
|
631
|
+
io.write "This is a test."
|
632
|
+
|
633
|
+
io.reread # => "This is a test."
|
634
|
+
io.reread 4 # => "This"
|
309
635
|
|
310
|
-
"
|
311
|
-
|
312
|
-
|
313
|
-
"".to_bool # => false
|
314
|
-
"example".to_bool # => false
|
636
|
+
buffer = "".dup
|
637
|
+
io.reread(buffer: buffer)
|
638
|
+
buffer # => "This is a test."
|
315
639
|
----
|
316
640
|
|
317
641
|
== Tests
|
data/lib/refinements.rb
CHANGED
data/lib/refinements/arrays.rb
CHANGED
data/lib/refinements/files.rb
CHANGED
data/lib/refinements/hashes.rb
CHANGED
@@ -2,6 +2,16 @@
|
|
2
2
|
|
3
3
|
module Refinements
|
4
4
|
module Hashes
|
5
|
+
refine Hash.singleton_class do
|
6
|
+
def infinite
|
7
|
+
new { |new_hash, missing_key| new_hash[missing_key] = new(&new_hash.default_proc) }
|
8
|
+
end
|
9
|
+
|
10
|
+
def with_default value
|
11
|
+
new { |new_hash, missing_key| new_hash[missing_key] = value }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
5
15
|
refine Hash do
|
6
16
|
def except *keys
|
7
17
|
reject { |key, _value| keys.include? key }
|
@@ -11,6 +21,25 @@ module Refinements
|
|
11
21
|
replace except(*keys)
|
12
22
|
end
|
13
23
|
|
24
|
+
# :reek:TooManyStatements
|
25
|
+
def flatten_keys prefix: nil, delimiter: "_", cast: :to_sym
|
26
|
+
fail StandardError, "Unknown cast: #{cast}." unless %i[to_sym to_s].include? cast
|
27
|
+
|
28
|
+
reduce({}) do |flat, (key, value)|
|
29
|
+
flat_key = prefix ? "#{prefix}#{delimiter}#{key}" : key
|
30
|
+
|
31
|
+
next flat.merge flat_key.public_send(cast) => value unless value.is_a? self.class
|
32
|
+
|
33
|
+
flat.merge(
|
34
|
+
recurse { value.flatten_keys prefix: flat_key, delimiter: delimiter, cast: cast }
|
35
|
+
)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def flatten_keys! prefix: nil, delimiter: "_", cast: :to_sym
|
40
|
+
replace flatten_keys(prefix: prefix, delimiter: delimiter, cast: cast)
|
41
|
+
end
|
42
|
+
|
14
43
|
def symbolize_keys
|
15
44
|
reduce({}) { |hash, (key, value)| hash.merge key.to_sym => value }
|
16
45
|
end
|
@@ -20,13 +49,9 @@ module Refinements
|
|
20
49
|
end
|
21
50
|
|
22
51
|
def deep_merge other
|
23
|
-
dup.deep_merge! other
|
24
|
-
end
|
25
|
-
|
26
|
-
def deep_merge! other
|
27
52
|
clazz = self.class
|
28
53
|
|
29
|
-
merge
|
54
|
+
merge other do |_key, this_value, other_value|
|
30
55
|
if this_value.is_a?(clazz) && other_value.is_a?(clazz)
|
31
56
|
this_value.deep_merge other_value
|
32
57
|
else
|
@@ -35,12 +60,16 @@ module Refinements
|
|
35
60
|
end
|
36
61
|
end
|
37
62
|
|
63
|
+
def deep_merge! other
|
64
|
+
replace deep_merge(other)
|
65
|
+
end
|
66
|
+
|
38
67
|
def deep_symbolize_keys
|
39
68
|
recurse(&:symbolize_keys)
|
40
69
|
end
|
41
70
|
|
42
71
|
def deep_symbolize_keys!
|
43
|
-
|
72
|
+
replace deep_symbolize_keys
|
44
73
|
end
|
45
74
|
|
46
75
|
def recurse &block
|
@@ -65,12 +94,12 @@ module Refinements
|
|
65
94
|
|
66
95
|
def reverse_merge other
|
67
96
|
warn "[DEPRECATION]: #reverse_merge is deprecated, use #merge instead."
|
68
|
-
other
|
97
|
+
merge(other) { |_key, old_value, _new_value| old_value }
|
69
98
|
end
|
70
99
|
|
71
100
|
def reverse_merge! other
|
72
101
|
warn "[DEPRECATION]: #reverse_merge! is deprecated, use #merge! instead."
|
73
|
-
|
102
|
+
replace reverse_merge(other)
|
74
103
|
end
|
75
104
|
|
76
105
|
def use &block
|
data/lib/refinements/identity.rb
CHANGED
@@ -4,6 +4,14 @@ require "pathname"
|
|
4
4
|
|
5
5
|
module Refinements
|
6
6
|
module Pathnames
|
7
|
+
refine Kernel do
|
8
|
+
def Pathname object
|
9
|
+
return super(String(object)) unless object
|
10
|
+
|
11
|
+
super
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
7
15
|
refine Pathname do
|
8
16
|
def name
|
9
17
|
basename extname
|
@@ -15,20 +23,30 @@ module Refinements
|
|
15
23
|
self
|
16
24
|
end
|
17
25
|
|
18
|
-
def directories pattern = "*"
|
19
|
-
glob(pattern).select(&:directory?).sort
|
26
|
+
def directories pattern = "*", flag: File::FNM_SYSCASE
|
27
|
+
glob(pattern, flag).select(&:directory?).sort
|
20
28
|
end
|
21
29
|
|
22
30
|
def extensions
|
23
31
|
basename.to_s.split(/(?=\.)+/).tap(&:shift)
|
24
32
|
end
|
25
33
|
|
26
|
-
def files pattern = "*"
|
27
|
-
glob(pattern).select(&:file?).sort
|
34
|
+
def files pattern = "*", flag: File::FNM_SYSCASE
|
35
|
+
glob(pattern, flag).select(&:file?).sort
|
36
|
+
end
|
37
|
+
|
38
|
+
def gsub pattern, replacement
|
39
|
+
self.class.new to_s.gsub(pattern, replacement)
|
40
|
+
end
|
41
|
+
|
42
|
+
def relative_parent root_dir
|
43
|
+
relative_path_from(root_dir).parent
|
28
44
|
end
|
29
45
|
|
30
|
-
def relative_parent_from
|
31
|
-
|
46
|
+
def relative_parent_from root_dir
|
47
|
+
warn "[DEPRECATION]: Pathname#relative_parent_from is deprecated, " \
|
48
|
+
"use Pathname#relative_parent instead."
|
49
|
+
relative_parent root_dir
|
32
50
|
end
|
33
51
|
|
34
52
|
def make_ancestors
|
data/lib/refinements/strings.rb
CHANGED
@@ -2,9 +2,12 @@
|
|
2
2
|
|
3
3
|
module Refinements
|
4
4
|
module Strings
|
5
|
+
DELIMITERS = %r([a-z][A-Z]|\s*-\s*|\s*/\s*|\s*:+\s*|\s*_\s*|\s+).freeze
|
6
|
+
|
5
7
|
refine String.singleton_class do
|
6
8
|
def delimiters
|
7
|
-
|
9
|
+
warn "[DEPRECATION]: .delimiters is deprecated, use DELIMITERS instead."
|
10
|
+
DELIMITERS
|
8
11
|
end
|
9
12
|
end
|
10
13
|
|
@@ -17,20 +20,18 @@ module Refinements
|
|
17
20
|
return self[0] if max.zero?
|
18
21
|
return "" if max.negative?
|
19
22
|
|
20
|
-
self[
|
23
|
+
self[..(max - 1)]
|
21
24
|
end
|
22
25
|
|
23
|
-
# :reek:TooManyStatements
|
24
26
|
def last number = 0
|
25
27
|
return self if empty?
|
26
28
|
|
27
29
|
min = Integer number
|
28
|
-
max = size - 1
|
29
30
|
|
30
|
-
return self[
|
31
|
+
return self[size - 1] if min.zero?
|
31
32
|
return "" if min.negative?
|
32
33
|
|
33
|
-
self[(min + 1)..
|
34
|
+
self[(min + 1)..]
|
34
35
|
end
|
35
36
|
|
36
37
|
def blank?
|
@@ -50,33 +51,27 @@ module Refinements
|
|
50
51
|
end
|
51
52
|
|
52
53
|
def camelcase
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
up
|
59
|
-
end
|
54
|
+
return up unless match? DELIMITERS
|
55
|
+
|
56
|
+
split(%r(\s*-\s*|\s*/\s*|\s*:+\s*)).then { |parts| combine parts, :up, "::" }
|
57
|
+
.then { |text| text.split(/\s*_\s*|\s+/) }
|
58
|
+
.then { |parts| combine parts, :up }
|
60
59
|
end
|
61
60
|
|
62
61
|
def snakecase
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
downcase
|
69
|
-
end
|
62
|
+
return downcase unless match? DELIMITERS
|
63
|
+
|
64
|
+
split(%r(\s*-\s*|\s*/\s*|\s*:+\s*)).then { |parts| combine parts, :down, "/" }
|
65
|
+
.then { |text| text.split(/(?=[A-Z])|\s*_\s*|\s+/) }
|
66
|
+
.then { |parts| combine parts, :down, "_" }
|
70
67
|
end
|
71
68
|
|
72
69
|
def titleize
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
capitalize
|
79
|
-
end
|
70
|
+
return capitalize unless match? DELIMITERS
|
71
|
+
|
72
|
+
split(/(?=[A-Z])|\s*_\s*|\s*-\s*|\s+/).then { |parts| combine parts, :up, " " }
|
73
|
+
.then { |text| text.split %r(\s*/\s*|\s*:+\s*) }
|
74
|
+
.then { |parts| combine parts, :up, "/" }
|
80
75
|
end
|
81
76
|
|
82
77
|
def to_bool
|
metadata
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: refinements
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 7.
|
4
|
+
version: 7.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brooke Kuhlmann
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain:
|
11
11
|
- |
|
@@ -28,7 +28,7 @@ cert_chain:
|
|
28
28
|
2XV8FRa7/JimI07sPLC13eLY3xd/aYTi85Z782KIA4j0G8XEEWAX0ouBhlXPocZv
|
29
29
|
QWc=
|
30
30
|
-----END CERTIFICATE-----
|
31
|
-
date: 2020-
|
31
|
+
date: 2020-09-19 00:00:00.000000000 Z
|
32
32
|
dependencies:
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: bundler-audit
|
@@ -50,28 +50,28 @@ dependencies:
|
|
50
50
|
requirements:
|
51
51
|
- - "~>"
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version: '14.
|
53
|
+
version: '14.2'
|
54
54
|
type: :development
|
55
55
|
prerelease: false
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
57
57
|
requirements:
|
58
58
|
- - "~>"
|
59
59
|
- !ruby/object:Gem::Version
|
60
|
-
version: '14.
|
60
|
+
version: '14.2'
|
61
61
|
- !ruby/object:Gem::Dependency
|
62
|
-
name: git-
|
62
|
+
name: git-lint
|
63
63
|
requirement: !ruby/object:Gem::Requirement
|
64
64
|
requirements:
|
65
65
|
- - "~>"
|
66
66
|
- !ruby/object:Gem::Version
|
67
|
-
version: '
|
67
|
+
version: '1.0'
|
68
68
|
type: :development
|
69
69
|
prerelease: false
|
70
70
|
version_requirements: !ruby/object:Gem::Requirement
|
71
71
|
requirements:
|
72
72
|
- - "~>"
|
73
73
|
- !ruby/object:Gem::Version
|
74
|
-
version: '
|
74
|
+
version: '1.0'
|
75
75
|
- !ruby/object:Gem::Dependency
|
76
76
|
name: guard-rspec
|
77
77
|
requirement: !ruby/object:Gem::Requirement
|
@@ -162,14 +162,14 @@ dependencies:
|
|
162
162
|
requirements:
|
163
163
|
- - "~>"
|
164
164
|
- !ruby/object:Gem::Version
|
165
|
-
version: '0.
|
165
|
+
version: '0.89'
|
166
166
|
type: :development
|
167
167
|
prerelease: false
|
168
168
|
version_requirements: !ruby/object:Gem::Requirement
|
169
169
|
requirements:
|
170
170
|
- - "~>"
|
171
171
|
- !ruby/object:Gem::Version
|
172
|
-
version: '0.
|
172
|
+
version: '0.89'
|
173
173
|
- !ruby/object:Gem::Dependency
|
174
174
|
name: rubocop-performance
|
175
175
|
requirement: !ruby/object:Gem::Requirement
|
@@ -218,15 +218,15 @@ dependencies:
|
|
218
218
|
requirements:
|
219
219
|
- - "~>"
|
220
220
|
- !ruby/object:Gem::Version
|
221
|
-
version: '0.
|
221
|
+
version: '0.19'
|
222
222
|
type: :development
|
223
223
|
prerelease: false
|
224
224
|
version_requirements: !ruby/object:Gem::Requirement
|
225
225
|
requirements:
|
226
226
|
- - "~>"
|
227
227
|
- !ruby/object:Gem::Version
|
228
|
-
version: '0.
|
229
|
-
description:
|
228
|
+
version: '0.19'
|
229
|
+
description:
|
230
230
|
email:
|
231
231
|
- brooke@alchemists.io
|
232
232
|
executables: []
|
@@ -245,6 +245,7 @@ files:
|
|
245
245
|
- lib/refinements/hashes.rb
|
246
246
|
- lib/refinements/identity.rb
|
247
247
|
- lib/refinements/pathnames.rb
|
248
|
+
- lib/refinements/string_ios.rb
|
248
249
|
- lib/refinements/strings.rb
|
249
250
|
homepage: https://www.alchemists.io/projects/refinements
|
250
251
|
licenses:
|
@@ -254,7 +255,7 @@ metadata:
|
|
254
255
|
changelog_uri: https://www.alchemists.io/projects/refinements/changes.html
|
255
256
|
documentation_uri: https://www.alchemists.io/projects/refinements
|
256
257
|
source_code_uri: https://github.com/bkuhlmann/refinements
|
257
|
-
post_install_message:
|
258
|
+
post_install_message:
|
258
259
|
rdoc_options: []
|
259
260
|
require_paths:
|
260
261
|
- lib
|
@@ -269,8 +270,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
269
270
|
- !ruby/object:Gem::Version
|
270
271
|
version: '0'
|
271
272
|
requirements: []
|
272
|
-
rubygems_version: 3.1.
|
273
|
-
signing_key:
|
273
|
+
rubygems_version: 3.1.4
|
274
|
+
signing_key:
|
274
275
|
specification_version: 4
|
275
276
|
summary: A collection of refinements to core Ruby objects.
|
276
277
|
test_files: []
|
metadata.gz.sig
CHANGED
Binary file
|