refinements 7.12.0 → 7.16.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 +370 -184
- data/lib/refinements.rb +1 -0
- data/lib/refinements/arrays.rb +14 -4
- data/lib/refinements/hashes.rb +45 -45
- data/lib/refinements/identity.rb +1 -1
- data/lib/refinements/ios.rb +4 -4
- data/lib/refinements/pathnames.rb +52 -10
- data/lib/refinements/strings.rb +29 -29
- data/lib/refinements/structs.rb +16 -0
- 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: 27c7f3818bd1f3d0d3fc39cb4c8721097d5003176b54710888deba6d012b4f77
|
4
|
+
data.tar.gz: f607fea47fce94c11c3ab7dcc6603b169567133fbbe6ca76fb0af0c9fa0196e4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: da5ff60dc1e6d4055adc850bbe7aa48d02c148f17fb42c9e50f939d577d506097603c2790cf5ce040cce1cb8389e28ebd363d3318d1224d06df4fc6d36e56b3f
|
7
|
+
data.tar.gz: a5a96d51b0e95d1f603262ca8ce767969e3faca18645327f368d8ee03aed7d0fa27211d9e35a8af30bcc6ca86d6dad33d804a4c9f1b830789b39b06dc0791793
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/README.adoc
CHANGED
@@ -6,6 +6,8 @@
|
|
6
6
|
|
7
7
|
[link=http://badge.fury.io/rb/refinements]
|
8
8
|
image::https://badge.fury.io/rb/refinements.svg[Gem Version]
|
9
|
+
[link=https://www.alchemists.io/projects/code_quality]
|
10
|
+
image::https://img.shields.io/badge/code_style-alchemists-brightgreen.svg[Alchemists Style Guide]
|
9
11
|
[link=https://circleci.com/gh/bkuhlmann/refinements]
|
10
12
|
image::https://circleci.com/gh/bkuhlmann/refinements.svg?style=svg[Circle CI Status]
|
11
13
|
|
@@ -26,6 +28,7 @@ Enhances the following objects:
|
|
26
28
|
* Pathname
|
27
29
|
* String
|
28
30
|
* StringIO
|
31
|
+
* Structs
|
29
32
|
|
30
33
|
== Requirements
|
31
34
|
|
@@ -73,6 +76,7 @@ require "refinements/ios"
|
|
73
76
|
require "refinements/pathnames"
|
74
77
|
require "refinements/strings"
|
75
78
|
require "refinements/string_ios"
|
79
|
+
require "refinements/structs"
|
76
80
|
----
|
77
81
|
|
78
82
|
=== Using
|
@@ -92,6 +96,7 @@ class Example
|
|
92
96
|
using Refinements::Pathnames
|
93
97
|
using Refinements::Strings
|
94
98
|
using Refinements::StringIOs
|
99
|
+
using Refinements::Structs
|
95
100
|
end
|
96
101
|
----
|
97
102
|
|
@@ -123,35 +128,35 @@ example.compress! # => ["An", "Example"]
|
|
123
128
|
example # => ["An", "Example"]
|
124
129
|
----
|
125
130
|
|
126
|
-
===== #
|
131
|
+
===== #excluding
|
127
132
|
|
128
|
-
|
133
|
+
Removes given array or elements without mutating itself.
|
129
134
|
|
130
135
|
[source,ruby]
|
131
136
|
----
|
132
|
-
[1, 2, 3].
|
133
|
-
[1, 2, 3].
|
137
|
+
[1, 2, 3, 4, 5].excluding [4, 5] # => [1, 2, 3]
|
138
|
+
[1, 2, 3, 4, 5].excluding 4, 5 # => [1, 2, 3]
|
134
139
|
----
|
135
140
|
|
136
|
-
===== #
|
141
|
+
===== #including
|
137
142
|
|
138
|
-
|
143
|
+
Adds given array or elements without mutating itself.
|
139
144
|
|
140
145
|
[source,ruby]
|
141
146
|
----
|
142
|
-
[1, 2, 3].
|
143
|
-
[1, 2, 3].
|
144
|
-
[1, 2, 3].intersperse %i[a b c] # => [1, :a, :b, :c, 2, :a, :b, :c, 3]
|
147
|
+
[1, 2, 3].including [4, 5] # => [1, 2, 3, 4, 5]
|
148
|
+
[1, 2, 3].including 4, 5 # => [1, 2, 3, 4, 5]
|
145
149
|
----
|
146
150
|
|
147
|
-
===== #
|
151
|
+
===== #intersperse
|
148
152
|
|
149
|
-
|
153
|
+
Inserts additional elements or array between all members of given array.
|
150
154
|
|
151
155
|
[source,ruby]
|
152
156
|
----
|
153
|
-
[1, 2, 3
|
154
|
-
[1, 2, 3
|
157
|
+
[1, 2, 3].intersperse :a # => [1, :a, 2, :a, 3]
|
158
|
+
[1, 2, 3].intersperse :a, :b # => [1, :a, :b, 2, :a, :b, 3]
|
159
|
+
[1, 2, 3].intersperse %i[a b c] # => [1, :a, :b, :c, 2, :a, :b, :c, 3]
|
155
160
|
----
|
156
161
|
|
157
162
|
===== #mean
|
@@ -235,106 +240,10 @@ Answers new hash where every top-level missing key has the same default value.
|
|
235
240
|
[source,ruby]
|
236
241
|
----
|
237
242
|
example = Hash.with_default ""
|
238
|
-
example[:a]
|
243
|
+
example[:a] # => ""
|
239
244
|
|
240
245
|
example = Hash.with_default []
|
241
|
-
example[:b]
|
242
|
-
----
|
243
|
-
|
244
|
-
===== #except
|
245
|
-
|
246
|
-
Answers new hash with given keys removed without mutating itself.
|
247
|
-
|
248
|
-
[source,ruby]
|
249
|
-
----
|
250
|
-
example = {a: 1, b: 2, c: 3}
|
251
|
-
example.except :a, :b # => {c: 3}
|
252
|
-
example # => {a: 1, b: 2, c: 3}
|
253
|
-
----
|
254
|
-
|
255
|
-
===== #except!
|
256
|
-
|
257
|
-
Answers new hash with given keys removed while mutating itself.
|
258
|
-
|
259
|
-
[source,ruby]
|
260
|
-
----
|
261
|
-
example = {a: 1, b: 2, c: 3}
|
262
|
-
example.except! :a, :b # => {c: 3}
|
263
|
-
example # => {c: 3}
|
264
|
-
----
|
265
|
-
|
266
|
-
===== #flatten_keys
|
267
|
-
|
268
|
-
Flattens nested keys as top-level keys without mutating itself. Does not handle nested arrays,
|
269
|
-
though.
|
270
|
-
|
271
|
-
[source,ruby]
|
272
|
-
----
|
273
|
-
{a: {b: 1}}.flatten_keys prefix: :test # => {test_a_b: 1}
|
274
|
-
{a: {b: 1}}.flatten_keys delimiter: :| # => {:"a|b" => 1}
|
275
|
-
|
276
|
-
{a: {b: 1}}.flatten_keys cast: :to_s # => {"a_b" => 1}
|
277
|
-
{"a" => {"b" => 1}}.flatten_keys cast: :to_sym # => {a_b: 1}
|
278
|
-
|
279
|
-
example = {a: {b: 1}}
|
280
|
-
example.flatten_keys # => {a_b: 1}
|
281
|
-
example # => {a: {b: 1}}
|
282
|
-
----
|
283
|
-
|
284
|
-
===== #flatten_keys!
|
285
|
-
|
286
|
-
Flattens nested keys as top-level keys while mutating itself. Does not handle nested arrays,
|
287
|
-
though.
|
288
|
-
|
289
|
-
[source,ruby]
|
290
|
-
----
|
291
|
-
example = {a: {b: 1}}
|
292
|
-
example.flatten_keys! # => {a_b: 1}
|
293
|
-
example # => {a_b: 1}
|
294
|
-
----
|
295
|
-
|
296
|
-
===== #stringify_keys
|
297
|
-
|
298
|
-
Converts keys to strings without mutating itself.
|
299
|
-
|
300
|
-
[source,ruby]
|
301
|
-
----
|
302
|
-
example = {a: 1, b: 2}
|
303
|
-
example.stringify_keys # => {"a" => 1, "b" => 2}
|
304
|
-
example # => {a: 1, b: 2}
|
305
|
-
----
|
306
|
-
|
307
|
-
===== #stringify_keys!
|
308
|
-
|
309
|
-
Converts keys to strings while mutating itself.
|
310
|
-
|
311
|
-
[source,ruby]
|
312
|
-
----
|
313
|
-
example = {a: 1, b: 2}
|
314
|
-
example.stringify_keys! # => {"a" => 1, "b" => 2}
|
315
|
-
example # => {"a" => 1, "b" => 2}
|
316
|
-
----
|
317
|
-
|
318
|
-
===== #symbolize_keys
|
319
|
-
|
320
|
-
Converts keys to symbols without mutating itself.
|
321
|
-
|
322
|
-
[source,ruby]
|
323
|
-
----
|
324
|
-
example = {"a" => 1, "b" => 2}
|
325
|
-
example.symbolize_keys # => {a: 1, b: 2}
|
326
|
-
example # => {"a" => 1, "b" => 2}
|
327
|
-
----
|
328
|
-
|
329
|
-
===== #symbolize_keys!
|
330
|
-
|
331
|
-
Converts keys to symbols while mutating itself.
|
332
|
-
|
333
|
-
[source,ruby]
|
334
|
-
----
|
335
|
-
example = {"a" => 1, "b" => 2}
|
336
|
-
example.symbolize_keys! # => {a: 1, b: 2}
|
337
|
-
example # => {a: 1, b: 2}
|
246
|
+
example[:b] # => []
|
338
247
|
----
|
339
248
|
|
340
249
|
===== #deep_merge
|
@@ -403,6 +312,58 @@ example.deep_symbolize_keys! # => {a: {b: 1}}
|
|
403
312
|
example # => {a: {b: 1}}
|
404
313
|
----
|
405
314
|
|
315
|
+
===== #except
|
316
|
+
|
317
|
+
Answers new hash with given keys removed without mutating itself.
|
318
|
+
|
319
|
+
[source,ruby]
|
320
|
+
----
|
321
|
+
example = {a: 1, b: 2, c: 3}
|
322
|
+
example.except :a, :b # => {c: 3}
|
323
|
+
example # => {a: 1, b: 2, c: 3}
|
324
|
+
----
|
325
|
+
|
326
|
+
===== #except!
|
327
|
+
|
328
|
+
Answers new hash with given keys removed while mutating itself.
|
329
|
+
|
330
|
+
[source,ruby]
|
331
|
+
----
|
332
|
+
example = {a: 1, b: 2, c: 3}
|
333
|
+
example.except! :a, :b # => {c: 3}
|
334
|
+
example # => {c: 3}
|
335
|
+
----
|
336
|
+
|
337
|
+
===== #flatten_keys
|
338
|
+
|
339
|
+
Flattens nested keys as top-level keys without mutating itself. Does not handle nested arrays,
|
340
|
+
though.
|
341
|
+
|
342
|
+
[source,ruby]
|
343
|
+
----
|
344
|
+
{a: {b: 1}}.flatten_keys prefix: :test # => {test_a_b: 1}
|
345
|
+
{a: {b: 1}}.flatten_keys delimiter: :| # => {:"a|b" => 1}
|
346
|
+
|
347
|
+
{a: {b: 1}}.flatten_keys cast: :to_s # => {"a_b" => 1}
|
348
|
+
{"a" => {"b" => 1}}.flatten_keys cast: :to_sym # => {a_b: 1}
|
349
|
+
|
350
|
+
example = {a: {b: 1}}
|
351
|
+
example.flatten_keys # => {a_b: 1}
|
352
|
+
example # => {a: {b: 1}}
|
353
|
+
----
|
354
|
+
|
355
|
+
===== #flatten_keys!
|
356
|
+
|
357
|
+
Flattens nested keys as top-level keys while mutating itself. Does not handle nested arrays,
|
358
|
+
though.
|
359
|
+
|
360
|
+
[source,ruby]
|
361
|
+
----
|
362
|
+
example = {a: {b: 1}}
|
363
|
+
example.flatten_keys! # => {a_b: 1}
|
364
|
+
example # => {a_b: 1}
|
365
|
+
----
|
366
|
+
|
406
367
|
===== #recurse
|
407
368
|
|
408
369
|
Recursively iterates over the hash and any hash value by applying the given block to it. Does not
|
@@ -459,6 +420,50 @@ example.reverse_merge! a: 0, c: 3 # => {a: 1, b: 2, c: 3}
|
|
459
420
|
example # => {a: 1, b: 2, c: 3}
|
460
421
|
----
|
461
422
|
|
423
|
+
===== #stringify_keys
|
424
|
+
|
425
|
+
Converts keys to strings without mutating itself.
|
426
|
+
|
427
|
+
[source,ruby]
|
428
|
+
----
|
429
|
+
example = {a: 1, b: 2}
|
430
|
+
example.stringify_keys # => {"a" => 1, "b" => 2}
|
431
|
+
example # => {a: 1, b: 2}
|
432
|
+
----
|
433
|
+
|
434
|
+
===== #stringify_keys!
|
435
|
+
|
436
|
+
Converts keys to strings while mutating itself.
|
437
|
+
|
438
|
+
[source,ruby]
|
439
|
+
----
|
440
|
+
example = {a: 1, b: 2}
|
441
|
+
example.stringify_keys! # => {"a" => 1, "b" => 2}
|
442
|
+
example # => {"a" => 1, "b" => 2}
|
443
|
+
----
|
444
|
+
|
445
|
+
===== #symbolize_keys
|
446
|
+
|
447
|
+
Converts keys to symbols without mutating itself.
|
448
|
+
|
449
|
+
[source,ruby]
|
450
|
+
----
|
451
|
+
example = {"a" => 1, "b" => 2}
|
452
|
+
example.symbolize_keys # => {a: 1, b: 2}
|
453
|
+
example # => {"a" => 1, "b" => 2}
|
454
|
+
----
|
455
|
+
|
456
|
+
===== #symbolize_keys!
|
457
|
+
|
458
|
+
Converts keys to symbols while mutating itself.
|
459
|
+
|
460
|
+
[source,ruby]
|
461
|
+
----
|
462
|
+
example = {"a" => 1, "b" => 2}
|
463
|
+
example.symbolize_keys! # => {a: 1, b: 2}
|
464
|
+
example # => {a: 1, b: 2}
|
465
|
+
----
|
466
|
+
|
462
467
|
===== #use
|
463
468
|
|
464
469
|
Passes each hash value as a block argument for further processing.
|
@@ -466,7 +471,7 @@ Passes each hash value as a block argument for further processing.
|
|
466
471
|
[source,ruby]
|
467
472
|
----
|
468
473
|
example = {unit: "221B", street: "Baker Street", city: "London", country: "UK"}
|
469
|
-
example.use { |unit, street| "#{unit} #{street}" }
|
474
|
+
example.use { |unit, street| "#{unit} #{street}" } # => "221B Baker Street"
|
470
475
|
----
|
471
476
|
|
472
477
|
==== IO
|
@@ -479,23 +484,8 @@ block, you'll need to close the stream manually.
|
|
479
484
|
|
480
485
|
[source,ruby]
|
481
486
|
----
|
482
|
-
io = IO.void
|
483
|
-
io.
|
484
|
-
|
485
|
-
io = IO.void { |void| void.write "nevermore" }
|
486
|
-
io.closed? # => true
|
487
|
-
----
|
488
|
-
|
489
|
-
===== #squelch
|
490
|
-
|
491
|
-
Temporarily ignores any reads/writes for current stream for all code executed within the block. When
|
492
|
-
not given a block, it answers itself.
|
493
|
-
|
494
|
-
[source,ruby]
|
495
|
-
----
|
496
|
-
io = IO.new IO.sysopen(Pathname("test.txt").to_s, "w+")
|
497
|
-
io.squelch { io.write "Test" }
|
498
|
-
io.reread # => ""
|
487
|
+
io = IO.void # => #<IO:fd 20>
|
488
|
+
io = IO.void { |void| void.write "nevermore" } # => #<IO:(closed)>
|
499
489
|
----
|
500
490
|
|
501
491
|
===== #redirect
|
@@ -508,11 +498,8 @@ answered instead.
|
|
508
498
|
io = IO.new IO.sysopen(Pathname("test.txt").to_s, "w+")
|
509
499
|
other = IO.new IO.sysopen(Pathname("other.txt").to_s, "w+")
|
510
500
|
|
511
|
-
io.redirect other
|
512
|
-
|
513
|
-
io.redirect(other) { |stream| stream.write "test" }
|
514
|
-
.close # => ""
|
515
|
-
other.close # => "test"
|
501
|
+
io.redirect other # => #<IO:fd 20>
|
502
|
+
io.redirect(other) { |stream| stream.write "test" } # => #<IO:fd 21>
|
516
503
|
----
|
517
504
|
|
518
505
|
===== #reread
|
@@ -528,45 +515,134 @@ io.reread # => "This is a test."
|
|
528
515
|
io.reread 4 # => "This"
|
529
516
|
|
530
517
|
buffer = "".dup
|
531
|
-
io.reread(buffer: buffer)
|
532
|
-
buffer
|
518
|
+
io.reread(buffer: buffer) # => "This is a test."
|
519
|
+
buffer # => "This is a test."
|
520
|
+
----
|
521
|
+
|
522
|
+
===== #squelch
|
523
|
+
|
524
|
+
Temporarily ignores any reads/writes for code executed within a block. Answers itself without any
|
525
|
+
arguments or when given a block.
|
526
|
+
|
527
|
+
[source,ruby]
|
528
|
+
----
|
529
|
+
io = IO.new IO.sysopen(Pathname("test.txt").to_s, "w+")
|
530
|
+
io.squelch # => #<IO:fd 20>
|
531
|
+
io.squelch { io.write "Test" } # => #<IO:fd 20>
|
532
|
+
io.reread # => ""
|
533
533
|
----
|
534
534
|
|
535
535
|
==== Pathname
|
536
536
|
|
537
537
|
===== Pathname
|
538
538
|
|
539
|
-
Enhances the
|
540
|
-
|
541
|
-
|
542
|
-
|
539
|
+
Enhances the `Kernel` conversion function which casts `nil` into a pathname in order to avoid:
|
540
|
+
`TypeError (no implicit conversion of nil into String)`. The pathname remains invalid but at least
|
541
|
+
you have an instance of `Pathname`, which behaves like a _Null Object_, that can be used to
|
542
|
+
construct a valid path.
|
543
543
|
|
544
544
|
[source,ruby]
|
545
545
|
----
|
546
546
|
Pathname(nil) # => Pathname("")
|
547
547
|
----
|
548
548
|
|
549
|
-
=====
|
549
|
+
===== .home
|
550
550
|
|
551
|
-
Answers
|
551
|
+
Answers user home directory.
|
552
552
|
|
553
553
|
[source,ruby]
|
554
554
|
----
|
555
|
-
Pathname
|
555
|
+
Pathname.home # => Pathname "/Users/bkuhlmann"
|
556
|
+
----
|
557
|
+
|
558
|
+
===== .make_temp_dir
|
559
|
+
|
560
|
+
Wraps `Dir.mktmpdir` with the following behavior (see
|
561
|
+
link:https://rubyapi.org/o/Dir.mktmpdir#method-c-mktmpdir[Dir.mktmpdir] for details):
|
562
|
+
|
563
|
+
* *Without Block* - Answers a newly created Pathname instance which is not automatically cleaned up.
|
564
|
+
* *With Block* Yields a Pathname instance, answers result of given block, and automatidally cleans
|
565
|
+
up temporary directory after block exits.
|
566
|
+
|
567
|
+
The following examples use truncated temporary directories for illustration purposes only. In
|
568
|
+
reality, these paths will be longer depending on which operating system you are using.
|
569
|
+
|
570
|
+
[source,ruby]
|
571
|
+
----
|
572
|
+
Pathname.make_temp_dir # => Pathname:/var/folders/T/temp-20200101-16940-r8
|
573
|
+
Pathname.make_temp_dir prefix: "prefix-" # => Pathname:/var/folders/T/prefix-20200101-16940-r8
|
574
|
+
Pathname.make_temp_dir suffix: "-suffix" # => Pathname:/var/folders/T/temp-20200101-16940-r8-suffix
|
575
|
+
Pathname.make_temp_dir prefix: "prefix-", suffix: "-suffix" # => Pathname:/var/folders/T/prefix-20200101-16940-r8-suffix
|
576
|
+
Pathname.make_temp_dir root: "/example" # => Pathname:/example/temp-20200101-16940-r8
|
577
|
+
Pathname.make_temp_dir { "I am a block result" } # => "I am a block result"
|
578
|
+
Pathname.make_temp_dir { |path| path.join "sub_dir" } # => Pathname:/var/folders/T/temp-20200101-16940-r8/sub_dir
|
579
|
+
----
|
580
|
+
|
581
|
+
===== .require_tree
|
582
|
+
|
583
|
+
Requires all files in given root path and corresponding nested tree structure. All files are sorted
|
584
|
+
before being required to ensure consistent behavior. Example:
|
585
|
+
|
586
|
+
[source,rby]
|
587
|
+
----
|
588
|
+
# Before
|
589
|
+
Dir[File.join(__dir__, "support/shared_contexts/**/*.rb")].sort.each { |path| require path }
|
590
|
+
|
591
|
+
# After
|
592
|
+
Pathname.require_tree __dir__, "support/shared_contexts/**/*.rb"
|
593
|
+
----
|
594
|
+
|
595
|
+
The following are further examples of potential usage:
|
596
|
+
|
597
|
+
[source,ruby]
|
598
|
+
----
|
599
|
+
# Requires all files in root directory and below.
|
600
|
+
Pathname.require_tree __dir__
|
601
|
+
|
602
|
+
# Requires all files in `/test/**/*.rb` and below.
|
603
|
+
Pathname.require_tree "/test"
|
604
|
+
|
605
|
+
# Requires all files in RSpec shared examples directory structure.
|
606
|
+
Pathname.require_tree Bundler.root.join("spec"), "support/shared_examples/**/*.rb"
|
607
|
+
----
|
608
|
+
|
609
|
+
===== .root
|
610
|
+
|
611
|
+
Answers operating system root path.
|
612
|
+
|
613
|
+
[source,ruby]
|
614
|
+
----
|
615
|
+
Pathname.root # => Pathname "/"
|
616
|
+
----
|
617
|
+
|
618
|
+
===== #change_dir
|
619
|
+
|
620
|
+
Wraps `Dir.chdir` behavior by changing to directory of current path. See
|
621
|
+
link:https://rubyapi.org/o/Dir.chdir#method-c-chdir[Dir.chdir] for details.
|
622
|
+
|
623
|
+
[source,ruby]
|
624
|
+
----
|
625
|
+
Pathname.pwd # => "/"
|
626
|
+
Pathname("/test").make_dir.change_dir # => Pathname "/test"
|
627
|
+
Pathname.pwd # => "/test"
|
628
|
+
|
629
|
+
Pathname.pwd # => "/"
|
630
|
+
Pathname("/test").make_dir.change_dir { "example" } # => "example"
|
631
|
+
Pathname.pwd # => "/"
|
556
632
|
----
|
557
633
|
|
558
634
|
===== #copy
|
559
635
|
|
560
|
-
Copies file from current location to new location.
|
636
|
+
Copies file from current location to new location while answering itself so it can be chained.
|
561
637
|
|
562
638
|
[source,ruby]
|
563
639
|
----
|
564
|
-
Pathname("input.txt").copy Pathname("output.txt")
|
640
|
+
Pathname("input.txt").copy Pathname("output.txt") # => Pathname("input.txt")
|
565
641
|
----
|
566
642
|
|
567
643
|
===== #directories
|
568
644
|
|
569
|
-
Answers all or filtered directories for current path.
|
645
|
+
Answers all directories or filtered directories for current path.
|
570
646
|
|
571
647
|
[source,ruby]
|
572
648
|
----
|
@@ -581,12 +657,12 @@ Answers file extensions as an array.
|
|
581
657
|
|
582
658
|
[source,ruby]
|
583
659
|
----
|
584
|
-
Pathname("example.txt.erb").extensions
|
660
|
+
Pathname("example.txt.erb").extensions # => [".txt", ".erb"]
|
585
661
|
----
|
586
662
|
|
587
663
|
===== #files
|
588
664
|
|
589
|
-
Answers all or filtered files for current path.
|
665
|
+
Answers all files or filtered files for current path.
|
590
666
|
|
591
667
|
[source,ruby]
|
592
668
|
----
|
@@ -608,6 +684,48 @@ Pathname("/%placeholder%/some/%placeholder%").gsub("%placeholder%", "test")
|
|
608
684
|
# => Pathname("/test/some/test")
|
609
685
|
----
|
610
686
|
|
687
|
+
===== #make_ancestors
|
688
|
+
|
689
|
+
Ensures all ancestor directories are created for a path.
|
690
|
+
|
691
|
+
[source,ruby]
|
692
|
+
----
|
693
|
+
Pathname("/one/two").make_ancestors # => Pathname("/one/two")
|
694
|
+
Pathname("/one").exist? # => true
|
695
|
+
Pathname("/one/two").exist? # => false
|
696
|
+
----
|
697
|
+
|
698
|
+
===== #make_dir
|
699
|
+
|
700
|
+
Provides alternative `#mkdir` behavior by always answering itself (even when directory exists) and
|
701
|
+
not throwing errors when directory does exist in order to ensure the pathname can be chained.
|
702
|
+
|
703
|
+
[source,ruby]
|
704
|
+
----
|
705
|
+
Pathname("/one").make_dir # => Pathname("/one")
|
706
|
+
Pathname("/one").make_dir.make_dir # => Pathname("/one")
|
707
|
+
----
|
708
|
+
|
709
|
+
===== #make_path
|
710
|
+
|
711
|
+
Provides alternative `#mkpath` behavior by always answering itself (even when full path exists) and
|
712
|
+
not throwing errors when directory does exist in order to ensure the pathname can be chained.
|
713
|
+
|
714
|
+
[source,ruby]
|
715
|
+
----
|
716
|
+
Pathname("/one/two/three").make_path # => Pathname("/one/two/three")
|
717
|
+
Pathname("/one/two/three").make_path.make_path # => Pathname("/one/two/three")
|
718
|
+
----
|
719
|
+
|
720
|
+
===== #name
|
721
|
+
|
722
|
+
Answers file name without extension.
|
723
|
+
|
724
|
+
[source,ruby]
|
725
|
+
----
|
726
|
+
Pathname("example.txt").name # => Pathname("example")
|
727
|
+
----
|
728
|
+
|
611
729
|
===== #relative_parent
|
612
730
|
|
613
731
|
Answers relative path from parent directory. This is a complement to `#relative_path_from`.
|
@@ -617,26 +735,37 @@ Answers relative path from parent directory. This is a complement to `#relative_
|
|
617
735
|
Pathname("/one/two/three").relative_parent("/one") # => Pathname "two"
|
618
736
|
----
|
619
737
|
|
620
|
-
===== #
|
738
|
+
===== #remove_dir
|
621
739
|
|
622
|
-
|
740
|
+
Provides alternative `#rmdir` behavior by always answering itself (even when full path exists) and
|
741
|
+
not throwing errors when directory does exist in order to ensure the pathname can be chained.
|
623
742
|
|
624
743
|
[source,ruby]
|
625
744
|
----
|
626
|
-
Pathname("/
|
627
|
-
Pathname("/
|
628
|
-
Pathname("/
|
745
|
+
Pathname("/test").make_dir.remove_dir.exist? # => false
|
746
|
+
Pathname("/test").remove_dir # => Pathname("/test")
|
747
|
+
Pathname("/test").remove_dir.remove_dir # => Pathname("/test")
|
629
748
|
----
|
630
749
|
|
631
|
-
===== #
|
750
|
+
===== #remove_tree
|
632
751
|
|
633
|
-
|
634
|
-
errors when directory
|
752
|
+
Provides alternative `#rmtree` behavior by always answering itself (even when full path exists) and
|
753
|
+
not throwing errors when directory does exist in order to ensure the pathname can be chained.
|
635
754
|
|
636
755
|
[source,ruby]
|
637
756
|
----
|
638
|
-
|
639
|
-
|
757
|
+
parent_path = Pathname "/one"
|
758
|
+
child_path = parent_path.join "two"
|
759
|
+
|
760
|
+
child_path.make_path
|
761
|
+
child_path.remove_tree # => Pathname "/one/two"
|
762
|
+
child_path.exist? # => false
|
763
|
+
paremt_path.exist? # => true
|
764
|
+
|
765
|
+
child_path.make_path
|
766
|
+
parent_path.remove_tree # => Pathname "/one"
|
767
|
+
child_path.exist? # => false
|
768
|
+
parent_path.exist? # => false
|
640
769
|
----
|
641
770
|
|
642
771
|
===== #rewrite
|
@@ -646,7 +775,8 @@ immediate writing back to the same file.
|
|
646
775
|
|
647
776
|
[source,ruby]
|
648
777
|
----
|
649
|
-
Pathname("/test.txt").rewrite
|
778
|
+
Pathname("/test.txt").rewrite # => Pathname("/test.txt")
|
779
|
+
Pathname("/test.txt").rewrite { |body| body.sub "[token]", "example" } # => Pathname("/test.txt")
|
650
780
|
----
|
651
781
|
|
652
782
|
===== #touch
|
@@ -655,31 +785,23 @@ Updates access and modification times for path. Defaults to current time.
|
|
655
785
|
|
656
786
|
[source,ruby]
|
657
787
|
----
|
658
|
-
Pathname("example.txt").touch
|
659
|
-
Pathname("example.txt").touch at: Time.now - 1
|
788
|
+
Pathname("example.txt").touch # => Pathname("example.txt")
|
789
|
+
Pathname("example.txt").touch at: Time.now - 1 # => Pathname("example.txt")
|
660
790
|
----
|
661
791
|
|
662
|
-
|
792
|
+
===== #write
|
663
793
|
|
664
|
-
|
665
|
-
|
666
|
-
Answers first character of a string or first set of characters if given a number.
|
794
|
+
Writes to file and answers itself so it can be chained. See `IO.write` for details on additional
|
795
|
+
options.
|
667
796
|
|
668
797
|
[source,ruby]
|
669
798
|
----
|
670
|
-
"example".
|
671
|
-
"example".
|
799
|
+
Pathname("example.txt").write "test" # => Pathname("example.txt")
|
800
|
+
Pathname("example.txt").write "test", offset: 1 # => Pathname("example.txt")
|
801
|
+
Pathname("example.txt").write "test", mode: "a" # => Pathname("example.txt")
|
672
802
|
----
|
673
803
|
|
674
|
-
|
675
|
-
|
676
|
-
Answers last character of a string or last set of characters if given a number.
|
677
|
-
|
678
|
-
[source,ruby]
|
679
|
-
----
|
680
|
-
"instant".last # => "t"
|
681
|
-
"instant".last 3 # => "ant"
|
682
|
-
----
|
804
|
+
==== String
|
683
805
|
|
684
806
|
===== #blank?
|
685
807
|
|
@@ -690,13 +812,13 @@ Answers `true`/`false` based on whether string is blank, `<space>`, `\n`, `\t`,
|
|
690
812
|
" \n\t\r".blank? # => true
|
691
813
|
----
|
692
814
|
|
693
|
-
===== #
|
815
|
+
===== #camelcase
|
694
816
|
|
695
|
-
Answers
|
817
|
+
Answers a camelcased string.
|
696
818
|
|
697
819
|
[source,ruby]
|
698
820
|
----
|
699
|
-
"
|
821
|
+
"this_is_an_example".camelcase # => "ThisIsAnExample"
|
700
822
|
----
|
701
823
|
|
702
824
|
===== #down
|
@@ -708,6 +830,16 @@ Answers string with only first letter downcased.
|
|
708
830
|
"EXAMPLE".down # => "eXAMPLE"
|
709
831
|
----
|
710
832
|
|
833
|
+
===== #first
|
834
|
+
|
835
|
+
Answers first character of a string or first set of characters if given a number.
|
836
|
+
|
837
|
+
[source,ruby]
|
838
|
+
----
|
839
|
+
"example".first # => "e"
|
840
|
+
"example".first 4 # => "exam"
|
841
|
+
----
|
842
|
+
|
711
843
|
===== #indent
|
712
844
|
|
713
845
|
Answers string indented by two spaces by default.
|
@@ -721,13 +853,14 @@ Answers string indented by two spaces by default.
|
|
721
853
|
"example".indent 3, padding: " " # => " example"
|
722
854
|
----
|
723
855
|
|
724
|
-
===== #
|
856
|
+
===== #last
|
725
857
|
|
726
|
-
Answers a
|
858
|
+
Answers last character of a string or last set of characters if given a number.
|
727
859
|
|
728
860
|
[source,ruby]
|
729
861
|
----
|
730
|
-
"
|
862
|
+
"instant".last # => "t"
|
863
|
+
"instant".last 3 # => "ant"
|
731
864
|
----
|
732
865
|
|
733
866
|
===== #snakecase
|
@@ -761,6 +894,15 @@ Answers string as a boolean.
|
|
761
894
|
"example".to_bool # => false
|
762
895
|
----
|
763
896
|
|
897
|
+
===== #up
|
898
|
+
|
899
|
+
Answers string with only first letter upcased.
|
900
|
+
|
901
|
+
[source,ruby]
|
902
|
+
----
|
903
|
+
"example".up # => "Example"
|
904
|
+
----
|
905
|
+
|
764
906
|
==== String IO
|
765
907
|
|
766
908
|
===== #reread
|
@@ -776,8 +918,52 @@ io.reread # => "This is a test."
|
|
776
918
|
io.reread 4 # => "This"
|
777
919
|
|
778
920
|
buffer = "".dup
|
779
|
-
io.reread(buffer: buffer)
|
780
|
-
buffer
|
921
|
+
io.reread(buffer: buffer) # => "This is a test."
|
922
|
+
buffer # => "This is a test."
|
923
|
+
----
|
924
|
+
|
925
|
+
==== Struct
|
926
|
+
|
927
|
+
===== #merge
|
928
|
+
|
929
|
+
Merges multiple attributes without mutating itself.
|
930
|
+
|
931
|
+
[source,ruby]
|
932
|
+
----
|
933
|
+
Example = Struct.new :a, :b, :c
|
934
|
+
example = Example[1, 2, 3]
|
935
|
+
example.merge a: 10 # => #<struct a=10, b=2, c=3>
|
936
|
+
example.merge a: 10, c: 30 # => #<struct a=10, b=2, c=30>
|
937
|
+
example.merge a: 10, b: 20, c: 30 # => #<struct a=10, b=20, c=30>
|
938
|
+
example # => #<struct a=1, b=2, c=3>
|
939
|
+
|
940
|
+
Example = Struct.new :a, :b, :c, keyword_init: true
|
941
|
+
example = Example[a: 1, b: 2, c: 3]
|
942
|
+
example.merge a: 10 # => #<struct a=10, b=2, c=3>
|
943
|
+
example.merge a: 10, c: 30 # => #<struct a=10, b=2, c=30>
|
944
|
+
example.merge a: 10, b: 20, c: 30 # => #<struct a=10, b=20, c=30>
|
945
|
+
example # => #<struct a=1, b=2, c=3>
|
946
|
+
----
|
947
|
+
|
948
|
+
===== #merge!
|
949
|
+
|
950
|
+
Merges multiple attributes while mutating itself.
|
951
|
+
|
952
|
+
[source,ruby]
|
953
|
+
----
|
954
|
+
Example = Struct.new :a, :b, :c
|
955
|
+
example = Example[1, 2, 3]
|
956
|
+
example.merge! a: 10 # => #<struct a=10, b=2, c=3>
|
957
|
+
example.merge! a: 10, c: 30 # => #<struct a=10, b=2, c=30>
|
958
|
+
example.merge! a: 10, b: 20, c: 30 # => #<struct a=10, b=20, c=30>
|
959
|
+
example # => #<struct a=10, b=20, c=30>
|
960
|
+
|
961
|
+
Example = Struct.new :a, :b, :c, keyword_init: true
|
962
|
+
example = Example[a: 1, b: 2, c: 3]
|
963
|
+
example.merge! a: 10 # => #<struct a=10, b=2, c=3>
|
964
|
+
example.merge! a: 10, c: 30 # => #<struct a=10, b=2, c=30>
|
965
|
+
example.merge! a: 10, b: 20, c: 30 # => #<struct a=10, b=20, c=30>
|
966
|
+
example # => #<struct a=10, b=20, c=30>
|
781
967
|
----
|
782
968
|
|
783
969
|
== Development
|
data/lib/refinements.rb
CHANGED
data/lib/refinements/arrays.rb
CHANGED
@@ -11,7 +11,21 @@ module Refinements
|
|
11
11
|
replace compress
|
12
12
|
end
|
13
13
|
|
14
|
+
def exclude *elements
|
15
|
+
warn "[DEPRECATION]: #exclude is deprecated, use #excluding instead."
|
16
|
+
excluding(*elements)
|
17
|
+
end
|
18
|
+
|
19
|
+
def excluding *elements
|
20
|
+
self - elements.flatten
|
21
|
+
end
|
22
|
+
|
14
23
|
def include *elements
|
24
|
+
warn "[DEPRECATION]: #include is deprecated, use #including instead."
|
25
|
+
including(*elements)
|
26
|
+
end
|
27
|
+
|
28
|
+
def including *elements
|
15
29
|
self + elements.flatten
|
16
30
|
end
|
17
31
|
|
@@ -19,10 +33,6 @@ module Refinements
|
|
19
33
|
product([elements]).tap(&:pop).flatten.push last
|
20
34
|
end
|
21
35
|
|
22
|
-
def exclude *elements
|
23
|
-
self - elements.flatten
|
24
|
-
end
|
25
|
-
|
26
36
|
def mean
|
27
37
|
size.zero? ? 0 : sum(0) / size
|
28
38
|
end
|
data/lib/refinements/hashes.rb
CHANGED
@@ -13,49 +13,6 @@ module Refinements
|
|
13
13
|
end
|
14
14
|
|
15
15
|
refine Hash do
|
16
|
-
def except *keys
|
17
|
-
reject { |key, _value| keys.include? key }
|
18
|
-
end
|
19
|
-
|
20
|
-
def except! *keys
|
21
|
-
replace except(*keys)
|
22
|
-
end
|
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
|
-
|
43
|
-
def stringify_keys
|
44
|
-
reduce({}) { |hash, (key, value)| hash.merge key.to_s => value }
|
45
|
-
end
|
46
|
-
|
47
|
-
def stringify_keys!
|
48
|
-
replace stringify_keys
|
49
|
-
end
|
50
|
-
|
51
|
-
def symbolize_keys
|
52
|
-
reduce({}) { |hash, (key, value)| hash.merge key.to_sym => value }
|
53
|
-
end
|
54
|
-
|
55
|
-
def symbolize_keys!
|
56
|
-
replace symbolize_keys
|
57
|
-
end
|
58
|
-
|
59
16
|
def deep_merge other
|
60
17
|
clazz = self.class
|
61
18
|
|
@@ -88,8 +45,35 @@ module Refinements
|
|
88
45
|
replace deep_symbolize_keys
|
89
46
|
end
|
90
47
|
|
48
|
+
def except *keys
|
49
|
+
reject { |key, _value| keys.include? key }
|
50
|
+
end
|
51
|
+
|
52
|
+
def except! *keys
|
53
|
+
replace except(*keys)
|
54
|
+
end
|
55
|
+
|
56
|
+
# :reek:TooManyStatements
|
57
|
+
def flatten_keys prefix: nil, delimiter: "_", cast: :to_sym
|
58
|
+
fail StandardError, "Unknown cast: #{cast}." unless %i[to_sym to_s].include? cast
|
59
|
+
|
60
|
+
reduce({}) do |flat, (key, value)|
|
61
|
+
flat_key = prefix ? "#{prefix}#{delimiter}#{key}" : key
|
62
|
+
|
63
|
+
next flat.merge flat_key.public_send(cast) => value unless value.is_a? self.class
|
64
|
+
|
65
|
+
flat.merge(
|
66
|
+
recurse { value.flatten_keys prefix: flat_key, delimiter: delimiter, cast: cast }
|
67
|
+
)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def flatten_keys! prefix: nil, delimiter: "_", cast: :to_sym
|
72
|
+
replace flatten_keys(prefix: prefix, delimiter: delimiter, cast: cast)
|
73
|
+
end
|
74
|
+
|
91
75
|
def recurse &block
|
92
|
-
return self unless
|
76
|
+
return self unless block
|
93
77
|
|
94
78
|
transform = yield self
|
95
79
|
|
@@ -118,8 +102,24 @@ module Refinements
|
|
118
102
|
replace reverse_merge(other)
|
119
103
|
end
|
120
104
|
|
105
|
+
def stringify_keys
|
106
|
+
reduce({}) { |hash, (key, value)| hash.merge key.to_s => value }
|
107
|
+
end
|
108
|
+
|
109
|
+
def stringify_keys!
|
110
|
+
replace stringify_keys
|
111
|
+
end
|
112
|
+
|
113
|
+
def symbolize_keys
|
114
|
+
reduce({}) { |hash, (key, value)| hash.merge key.to_sym => value }
|
115
|
+
end
|
116
|
+
|
117
|
+
def symbolize_keys!
|
118
|
+
replace symbolize_keys
|
119
|
+
end
|
120
|
+
|
121
121
|
def use &block
|
122
|
-
return [] unless
|
122
|
+
return [] unless block
|
123
123
|
|
124
124
|
block.parameters
|
125
125
|
.map { |(_type, key)| self[key] }
|
data/lib/refinements/identity.rb
CHANGED
data/lib/refinements/ios.rb
CHANGED
@@ -14,10 +14,6 @@ module Refinements
|
|
14
14
|
end
|
15
15
|
|
16
16
|
refine IO do
|
17
|
-
def squelch &block
|
18
|
-
self.class.void.then { |void| redirect(void, &block) }
|
19
|
-
end
|
20
|
-
|
21
17
|
def redirect other
|
22
18
|
return self unless block_given?
|
23
19
|
|
@@ -30,6 +26,10 @@ module Refinements
|
|
30
26
|
def reread length = nil, buffer: nil
|
31
27
|
tap(&:rewind).read length, buffer
|
32
28
|
end
|
29
|
+
|
30
|
+
def squelch &block
|
31
|
+
self.class.void.then { |void| redirect(void, &block) }
|
32
|
+
end
|
33
33
|
end
|
34
34
|
end
|
35
35
|
end
|
@@ -12,9 +12,27 @@ module Refinements
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
+
refine Pathname.singleton_class do
|
16
|
+
def home
|
17
|
+
new ENV["HOME"]
|
18
|
+
end
|
19
|
+
|
20
|
+
def make_temp_dir prefix: "temp-", suffix: nil, root: nil
|
21
|
+
Dir.mktmpdir([prefix, suffix], root) { |path| block_given? ? yield(new path) : new(path) }
|
22
|
+
end
|
23
|
+
|
24
|
+
def require_tree root, pattern = "**/*.rb"
|
25
|
+
new(root).files(pattern).each { |path| require path.to_s }
|
26
|
+
end
|
27
|
+
|
28
|
+
def root
|
29
|
+
new "/"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
15
33
|
refine Pathname do
|
16
|
-
def
|
17
|
-
|
34
|
+
def change_dir &block
|
35
|
+
block ? Dir.chdir(self, &block) : (Dir.chdir self and self)
|
18
36
|
end
|
19
37
|
|
20
38
|
def copy to
|
@@ -39,6 +57,28 @@ module Refinements
|
|
39
57
|
self.class.new to_s.gsub(pattern, replacement)
|
40
58
|
end
|
41
59
|
|
60
|
+
def make_ancestors
|
61
|
+
dirname.mkpath
|
62
|
+
self
|
63
|
+
end
|
64
|
+
|
65
|
+
def make_dir
|
66
|
+
exist? ? self : mkdir and self
|
67
|
+
end
|
68
|
+
|
69
|
+
def make_path
|
70
|
+
mkpath
|
71
|
+
self
|
72
|
+
end
|
73
|
+
|
74
|
+
def mkdir
|
75
|
+
exist? ? self : super and self
|
76
|
+
end
|
77
|
+
|
78
|
+
def name
|
79
|
+
basename extname
|
80
|
+
end
|
81
|
+
|
42
82
|
def relative_parent root_dir
|
43
83
|
relative_path_from(root_dir).parent
|
44
84
|
end
|
@@ -49,26 +89,28 @@ module Refinements
|
|
49
89
|
relative_parent root_dir
|
50
90
|
end
|
51
91
|
|
52
|
-
def
|
53
|
-
|
54
|
-
self
|
92
|
+
def remove_dir
|
93
|
+
exist? ? (rmdir and self) : self
|
55
94
|
end
|
56
95
|
|
57
|
-
|
58
|
-
|
59
|
-
self
|
96
|
+
def remove_tree
|
97
|
+
rmtree if exist?
|
98
|
+
self
|
60
99
|
end
|
61
|
-
# rubocop:enable Style/RedundantSelf
|
62
100
|
|
63
101
|
def rewrite
|
64
102
|
read.then { |content| write yield(content) if block_given? }
|
65
|
-
self
|
66
103
|
end
|
67
104
|
|
68
105
|
def touch at: Time.now
|
69
106
|
exist? ? utime(at, at) : write("")
|
70
107
|
self
|
71
108
|
end
|
109
|
+
|
110
|
+
def write content, offset: nil, **options
|
111
|
+
super content, offset, **options
|
112
|
+
self
|
113
|
+
end
|
72
114
|
end
|
73
115
|
end
|
74
116
|
end
|
data/lib/refinements/strings.rb
CHANGED
@@ -12,42 +12,33 @@ module Refinements
|
|
12
12
|
end
|
13
13
|
|
14
14
|
refine String do
|
15
|
-
def
|
16
|
-
|
17
|
-
|
18
|
-
max = Integer number
|
15
|
+
def blank?
|
16
|
+
match?(/\A\s*\z/)
|
17
|
+
end
|
19
18
|
|
20
|
-
|
21
|
-
return
|
19
|
+
def camelcase
|
20
|
+
return up unless match? DELIMITERS
|
22
21
|
|
23
|
-
|
22
|
+
split(%r(\s*-\s*|\s*/\s*|\s*:+\s*)).then { |parts| combine parts, :up, "::" }
|
23
|
+
.then { |text| text.split(/\s*_\s*|\s+/) }
|
24
|
+
.then { |parts| combine parts, :up }
|
24
25
|
end
|
25
26
|
|
26
|
-
def
|
27
|
+
def down
|
27
28
|
return self if empty?
|
28
29
|
|
29
|
-
|
30
|
-
|
31
|
-
return self[size - 1] if min.zero?
|
32
|
-
return "" if min.negative?
|
33
|
-
|
34
|
-
self[(min + 1)..]
|
35
|
-
end
|
36
|
-
|
37
|
-
def blank?
|
38
|
-
match?(/\A\s*\z/)
|
30
|
+
first.downcase + self[1, size]
|
39
31
|
end
|
40
32
|
|
41
|
-
def
|
33
|
+
def first number = 0
|
42
34
|
return self if empty?
|
43
35
|
|
44
|
-
|
45
|
-
end
|
36
|
+
max = Integer number
|
46
37
|
|
47
|
-
|
48
|
-
return
|
38
|
+
return self[0] if max.zero?
|
39
|
+
return "" if max.negative?
|
49
40
|
|
50
|
-
|
41
|
+
self[..(max - 1)]
|
51
42
|
end
|
52
43
|
|
53
44
|
def indent multiplier = 1, padding: " "
|
@@ -56,12 +47,15 @@ module Refinements
|
|
56
47
|
padding * multiplier + self
|
57
48
|
end
|
58
49
|
|
59
|
-
def
|
60
|
-
return
|
50
|
+
def last number = 0
|
51
|
+
return self if empty?
|
61
52
|
|
62
|
-
|
63
|
-
|
64
|
-
|
53
|
+
min = Integer number
|
54
|
+
|
55
|
+
return self[size - 1] if min.zero?
|
56
|
+
return "" if min.negative?
|
57
|
+
|
58
|
+
self[(min + 1)..]
|
65
59
|
end
|
66
60
|
|
67
61
|
def snakecase
|
@@ -84,6 +78,12 @@ module Refinements
|
|
84
78
|
%w[true yes on t y 1].include? downcase.strip
|
85
79
|
end
|
86
80
|
|
81
|
+
def up
|
82
|
+
return self if empty?
|
83
|
+
|
84
|
+
first.upcase + self[1, size]
|
85
|
+
end
|
86
|
+
|
87
87
|
private
|
88
88
|
|
89
89
|
# :reek:DuplicateMethodCall
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Refinements
|
4
|
+
module Structs
|
5
|
+
refine Struct do
|
6
|
+
def merge **attributes
|
7
|
+
dup.merge! attributes
|
8
|
+
end
|
9
|
+
|
10
|
+
def merge! **attributes
|
11
|
+
to_h.merge(attributes).each { |key, value| self[key] = value }
|
12
|
+
self
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: refinements
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 7.
|
4
|
+
version: 7.16.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brooke Kuhlmann
|
@@ -28,7 +28,7 @@ cert_chain:
|
|
28
28
|
2XV8FRa7/JimI07sPLC13eLY3xd/aYTi85Z782KIA4j0G8XEEWAX0ouBhlXPocZv
|
29
29
|
QWc=
|
30
30
|
-----END CERTIFICATE-----
|
31
|
-
date: 2020-11-
|
31
|
+
date: 2020-11-28 00:00:00.000000000 Z
|
32
32
|
dependencies:
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: bundler-audit
|
@@ -36,14 +36,14 @@ dependencies:
|
|
36
36
|
requirements:
|
37
37
|
- - "~>"
|
38
38
|
- !ruby/object:Gem::Version
|
39
|
-
version: '0.
|
39
|
+
version: '0.7'
|
40
40
|
type: :development
|
41
41
|
prerelease: false
|
42
42
|
version_requirements: !ruby/object:Gem::Requirement
|
43
43
|
requirements:
|
44
44
|
- - "~>"
|
45
45
|
- !ruby/object:Gem::Version
|
46
|
-
version: '0.
|
46
|
+
version: '0.7'
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: bundler-leak
|
49
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -64,28 +64,28 @@ dependencies:
|
|
64
64
|
requirements:
|
65
65
|
- - "~>"
|
66
66
|
- !ruby/object:Gem::Version
|
67
|
-
version: '14.
|
67
|
+
version: '14.8'
|
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: '14.
|
74
|
+
version: '14.8'
|
75
75
|
- !ruby/object:Gem::Dependency
|
76
76
|
name: git-lint
|
77
77
|
requirement: !ruby/object:Gem::Requirement
|
78
78
|
requirements:
|
79
79
|
- - "~>"
|
80
80
|
- !ruby/object:Gem::Version
|
81
|
-
version: '1.
|
81
|
+
version: '1.3'
|
82
82
|
type: :development
|
83
83
|
prerelease: false
|
84
84
|
version_requirements: !ruby/object:Gem::Requirement
|
85
85
|
requirements:
|
86
86
|
- - "~>"
|
87
87
|
- !ruby/object:Gem::Version
|
88
|
-
version: '1.
|
88
|
+
version: '1.3'
|
89
89
|
- !ruby/object:Gem::Dependency
|
90
90
|
name: guard-rspec
|
91
91
|
requirement: !ruby/object:Gem::Requirement
|
@@ -162,42 +162,42 @@ dependencies:
|
|
162
162
|
requirements:
|
163
163
|
- - "~>"
|
164
164
|
- !ruby/object:Gem::Version
|
165
|
-
version: '3.
|
165
|
+
version: '3.10'
|
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: '3.
|
172
|
+
version: '3.10'
|
173
173
|
- !ruby/object:Gem::Dependency
|
174
174
|
name: rubocop
|
175
175
|
requirement: !ruby/object:Gem::Requirement
|
176
176
|
requirements:
|
177
177
|
- - "~>"
|
178
178
|
- !ruby/object:Gem::Version
|
179
|
-
version: '
|
179
|
+
version: '1.3'
|
180
180
|
type: :development
|
181
181
|
prerelease: false
|
182
182
|
version_requirements: !ruby/object:Gem::Requirement
|
183
183
|
requirements:
|
184
184
|
- - "~>"
|
185
185
|
- !ruby/object:Gem::Version
|
186
|
-
version: '
|
186
|
+
version: '1.3'
|
187
187
|
- !ruby/object:Gem::Dependency
|
188
188
|
name: rubocop-performance
|
189
189
|
requirement: !ruby/object:Gem::Requirement
|
190
190
|
requirements:
|
191
191
|
- - "~>"
|
192
192
|
- !ruby/object:Gem::Version
|
193
|
-
version: '1.
|
193
|
+
version: '1.8'
|
194
194
|
type: :development
|
195
195
|
prerelease: false
|
196
196
|
version_requirements: !ruby/object:Gem::Requirement
|
197
197
|
requirements:
|
198
198
|
- - "~>"
|
199
199
|
- !ruby/object:Gem::Version
|
200
|
-
version: '1.
|
200
|
+
version: '1.8'
|
201
201
|
- !ruby/object:Gem::Dependency
|
202
202
|
name: rubocop-rake
|
203
203
|
requirement: !ruby/object:Gem::Requirement
|
@@ -218,14 +218,14 @@ dependencies:
|
|
218
218
|
requirements:
|
219
219
|
- - "~>"
|
220
220
|
- !ruby/object:Gem::Version
|
221
|
-
version: '
|
221
|
+
version: '2.0'
|
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: '
|
228
|
+
version: '2.0'
|
229
229
|
- !ruby/object:Gem::Dependency
|
230
230
|
name: simplecov
|
231
231
|
requirement: !ruby/object:Gem::Requirement
|
@@ -262,6 +262,7 @@ files:
|
|
262
262
|
- lib/refinements/pathnames.rb
|
263
263
|
- lib/refinements/string_ios.rb
|
264
264
|
- lib/refinements/strings.rb
|
265
|
+
- lib/refinements/structs.rb
|
265
266
|
homepage: https://www.alchemists.io/projects/refinements
|
266
267
|
licenses:
|
267
268
|
- Apache-2.0
|
metadata.gz.sig
CHANGED
Binary file
|