refinements 7.10.0 → 7.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2b7b36399c299675bc98b26334acc2466c5c506849e34b36534f21d2eed72e57
4
- data.tar.gz: 0d00c8e399a0d43c21dafef5985e9d0eb51fe7d544fbe93f4d184eafa75018a8
3
+ metadata.gz: 756d9dcbbc60385370835ad8001dd4fb84f6848aba8ca51cbe949fcd2aaa72a4
4
+ data.tar.gz: f09562bfe5991533c166f5aa0aa215a3f2fe8df3604e85dd3404a7688df67980
5
5
  SHA512:
6
- metadata.gz: 558191fc552ba160302b9189b8bd2e3ed17ceaee226426cf9453c0c65b8ca0e771b9e85be1e5453c8c1438bc52511a45afc218c72329c17570a6036b65e9f91f
7
- data.tar.gz: 69436b5353f1541b644f9ca72346da713bd8bb1c0f9595983392881727f06ea46ecacdea1412a929981ee24e0243865c6ac9274e747f04d3584c85216e7e300b
6
+ metadata.gz: b37235bf15f3b959dd295a22c3e9c89dff28faa4124da955b0e27b2bef7db505d3093dc56369550d2863e6dc2ca3d10bbfe248da1e7a70f0eaee7fb351bd4e9f
7
+ data.tar.gz: 0c7aeed58557e626cc6494d761e79c4a0bcb60f42e79d83cef01676c9fd5fbf838dd97f4b89c3234a978455d3acfb6bdd3f715ed55dfed05a92e5f0e86d7426d
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -150,7 +150,7 @@ additional liability.
150
150
 
151
151
  END OF TERMS AND CONDITIONS
152
152
 
153
- Copyright link:https://www.alchemists.io[Alchemists].
153
+ Copyright 2015 link:https://www.alchemists.io/team/brooke_kuhlmann[Brooke Kuhlmann].
154
154
 
155
155
  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
156
156
  compliance with the License. You may obtain a link:https://www.apache.org/licenses/LICENSE-2.0[copy]
@@ -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
 
@@ -22,9 +24,11 @@ Enhances the following objects:
22
24
  * DateTime
23
25
  * File
24
26
  * Hash
27
+ * IO
25
28
  * Pathname
26
29
  * String
27
30
  * StringIO
31
+ * Structs
28
32
 
29
33
  == Requirements
30
34
 
@@ -34,8 +38,6 @@ Enhances the following objects:
34
38
 
35
39
  == Setup
36
40
 
37
- === Production
38
-
39
41
  To install, run:
40
42
 
41
43
  [source,bash]
@@ -50,24 +52,6 @@ Add the following to your Gemfile file:
50
52
  gem "refinements"
51
53
  ----
52
54
 
53
- === Development
54
-
55
- To contribute, run:
56
-
57
- [source,bash]
58
- ----
59
- git clone https://github.com/bkuhlmann/refinements.git
60
- cd refinements
61
- bin/setup
62
- ----
63
-
64
- You can also use the IRB console for direct access to all objects:
65
-
66
- [source,bash]
67
- ----
68
- bin/console
69
- ----
70
-
71
55
  == Usage
72
56
 
73
57
  === Requires
@@ -79,7 +63,7 @@ If all refinements are not desired, add the following to your `+Gemfile+` instea
79
63
  gem "refinements", require: false
80
64
  ----
81
65
 
82
- then require the specific refinement, as needed. Example:
66
+ ...then require the specific refinement, as needed. Example:
83
67
 
84
68
  [source,ruby]
85
69
  ----
@@ -88,9 +72,11 @@ require "refinements/big_decimals"
88
72
  require "refinements/date_times"
89
73
  require "refinements/files"
90
74
  require "refinements/hashes"
75
+ require "refinements/ios"
91
76
  require "refinements/pathnames"
92
77
  require "refinements/strings"
93
78
  require "refinements/string_ios"
79
+ require "refinements/structs"
94
80
  ----
95
81
 
96
82
  === Using
@@ -106,9 +92,11 @@ class Example
106
92
  using Refinements::DateTimes
107
93
  using Refinements::Files
108
94
  using Refinements::Hashes
95
+ using Refinements::IOs
109
96
  using Refinements::Pathnames
110
97
  using Refinements::Strings
111
98
  using Refinements::StringIOs
99
+ using Refinements::Structs
112
100
  end
113
101
  ----
114
102
 
@@ -140,24 +128,47 @@ example.compress! # => ["An", "Example"]
140
128
  example # => ["An", "Example"]
141
129
  ----
142
130
 
143
- ===== #include
131
+ ===== #excluding
132
+
133
+ Removes given array or elements without mutating itself.
134
+
135
+ [source,ruby]
136
+ ----
137
+ [1, 2, 3, 4, 5].excluding [4, 5] # => [1, 2, 3]
138
+ [1, 2, 3, 4, 5].excluding 4, 5 # => [1, 2, 3]
139
+ ----
140
+
141
+ ===== #including
144
142
 
145
143
  Adds given array or elements without mutating itself.
146
144
 
147
145
  [source,ruby]
148
146
  ----
149
- [1, 2, 3].include [4, 5] # => [1, 2, 3, 4, 5]
150
- [1, 2, 3].include 4, 5 # => [1, 2, 3, 4, 5]
147
+ [1, 2, 3].including [4, 5] # => [1, 2, 3, 4, 5]
148
+ [1, 2, 3].including 4, 5 # => [1, 2, 3, 4, 5]
151
149
  ----
152
150
 
153
- ===== #exclude
151
+ ===== #intersperse
154
152
 
155
- Removes given array or elements without mutating itself.
153
+ Inserts additional elements or array between all members of given array.
154
+
155
+ [source,ruby]
156
+ ----
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]
160
+ ----
161
+
162
+ ===== #mean
163
+
164
+ Answers mean/average all elements within an array.
156
165
 
157
166
  [source,ruby]
158
167
  ----
159
- [1, 2, 3, 4, 5].exclude [4, 5] # => [1, 2, 3]
160
- [1, 2, 3, 4, 5].exclude 4, 5 # => [1, 2, 3]
168
+ [].mean # => 0
169
+ [5].mean # => 5
170
+ [1, 2, 3].mean # => 2
171
+ [1.25, 1.5, 1.75].mean # => 1.5
161
172
  ----
162
173
 
163
174
  ===== #ring
@@ -235,6 +246,72 @@ example = Hash.with_default []
235
246
  example[:b] # => []
236
247
  ----
237
248
 
249
+ ===== #deep_merge
250
+
251
+ Merges deeply nested hashes together without mutating itself.
252
+
253
+ [source,ruby]
254
+ ----
255
+ example = {a: "A", b: {one: "One", two: "Two"}}
256
+ example.deep_merge b: {one: 1} # => {a: "A", b: {one: 1, two: "Two"}}
257
+ example # => {a: "A", b: {one: "One", two: "Two"}}
258
+ ----
259
+
260
+ ===== #deep_merge!
261
+
262
+ Merges deeply nested hashes together while mutating itself.
263
+
264
+ [source,ruby]
265
+ ----
266
+ example = {a: "A", b: {one: "One", two: "Two"}}
267
+ example.deep_merge! b: {one: 1} # => {a: "A", b: {one: 1, two: "Two"}}
268
+ example # => {a: "A", b: {one: 1, two: "Two"}}
269
+ ----
270
+
271
+ ===== #deep_stringify_keys
272
+
273
+ Stringifies keys of nested hash without mutating itself. Does not handle nested arrays, though.
274
+
275
+ [source,ruby]
276
+ ----
277
+ example = {a: {b: 2}}
278
+ example.deep_stringify_keys # => {"a" => {"b" => 1}}
279
+ example # => {a: {b: 2}}
280
+ ----
281
+
282
+ ===== #deep_stringify_keys!
283
+
284
+ Stringifies keys of nested hash while mutating itself. Does not handle nested arrays, though.
285
+
286
+ [source,ruby]
287
+ ----
288
+ example = {a: {b: 2}}
289
+ example.deep_stringify_keys! # => {"a" => {"b" => 1}}
290
+ example # => {"a" => {"b" => 1}}
291
+ ----
292
+
293
+ ===== #deep_symbolize_keys
294
+
295
+ Symbolizes keys of nested hash without mutating itself. Does not handle nested arrays, though.
296
+
297
+ [source,ruby]
298
+ ----
299
+ example = {"a" => {"b" => 2}}
300
+ example.deep_symbolize_keys # => {a: {b: 1}}
301
+ example # => {"a" => {"b" => 2}}
302
+ ----
303
+
304
+ ===== #deep_symbolize_keys!
305
+
306
+ Symbolizes keys of nested hash while mutating itself. Does not handle nested arrays, though.
307
+
308
+ [source,ruby]
309
+ ----
310
+ example = {"a" => {"b" => 2}}
311
+ example.deep_symbolize_keys! # => {a: {b: 1}}
312
+ example # => {a: {b: 1}}
313
+ ----
314
+
238
315
  ===== #except
239
316
 
240
317
  Answers new hash with given keys removed without mutating itself.
@@ -287,217 +364,216 @@ example.flatten_keys! # => {a_b: 1}
287
364
  example # => {a_b: 1}
288
365
  ----
289
366
 
290
- ===== #stringify_keys
367
+ ===== #recurse
291
368
 
292
- Converts keys to strings without mutating itself.
369
+ Recursively iterates over the hash and any hash value by applying the given block to it. Does not
370
+ handle nested arrays, though.
293
371
 
294
372
  [source,ruby]
295
373
  ----
296
- example = {a: 1, b: 2}
297
- example.stringify_keys # => {"a" => 1, "b" => 2}
298
- example # => {a: 1, b: 2}
374
+ example = {"a" => {"b" => 1}}
375
+ example.recurse(&:symbolize_keys) # => {a: {b: 1}}
376
+ example.recurse(&:invert) # => {{"b" => 1} => "a"}
299
377
  ----
300
378
 
301
- ===== #stringify_keys!
379
+ ===== #rekey
302
380
 
303
- Converts keys to strings while mutating itself.
381
+ Transforms keys per mapping (size of mapping can vary) without mutating itself.
304
382
 
305
383
  [source,ruby]
306
384
  ----
307
- example = {a: 1, b: 2}
308
- example.stringify_keys! # => {"a" => 1, "b" => 2}
309
- example # => {"a" => 1, "b" => 2}
385
+ example = {a: 1, b: 2, c: 3}
386
+ example.rekey a: :amber, b: :blue # => {amber: 1, blue: 2, c: 3}
387
+ example # => {a: 1, b: 2, c: 3}
310
388
  ----
311
389
 
312
- ===== #symbolize_keys
390
+ ===== #rekey!
313
391
 
314
- Converts keys to symbols without mutating itself.
392
+ Transforms keys per mapping (size of mapping can vary) while mutating itself.
315
393
 
316
394
  [source,ruby]
317
395
  ----
318
- example = {"a" => 1, "b" => 2}
319
- example.symbolize_keys # => {a: 1, b: 2}
320
- example # => {"a" => 1, "b" => 2}
396
+ example = {a: 1, b: 2, c: 3}
397
+ example.rekey! a: :amber, b: :blue # => {amber: 1, blue: 2, c: 3}
398
+ example # => {amber: 1, blue: 2, c: 3}
321
399
  ----
322
400
 
323
- ===== #symbolize_keys!
401
+ ===== #reverse_merge
324
402
 
325
- Converts keys to symbols while mutating itself.
403
+ Merges calling hash into passed in hash without mutating itself.
326
404
 
327
405
  [source,ruby]
328
406
  ----
329
- example = {"a" => 1, "b" => 2}
330
- example.symbolize_keys! # => {a: 1, b: 2}
331
- example # => {a: 1, b: 2}
407
+ example = {a: 1, b: 2}
408
+ example.reverse_merge a: 0, c: 3 # => {a: 1, b: 2, c: 3}
409
+ example # => {a: 1, b: 2}
332
410
  ----
333
411
 
334
- ===== #deep_merge
412
+ ===== #reverse_merge!
335
413
 
336
- Merges deeply nested hashes together without mutating itself.
414
+ Merges calling hash into passed in hash while mutating itself.
337
415
 
338
416
  [source,ruby]
339
417
  ----
340
- example = {a: "A", b: {one: "One", two: "Two"}}
341
- example.deep_merge b: {one: 1} # => {a: "A", b: {one: 1, two: "Two"}}
342
- example # => {a: "A", b: {one: "One", two: "Two"}}
418
+ example = {a: 1, b: 2}
419
+ example.reverse_merge! a: 0, c: 3 # => {a: 1, b: 2, c: 3}
420
+ example # => {a: 1, b: 2, c: 3}
343
421
  ----
344
422
 
345
- ===== #deep_merge!
423
+ ===== #stringify_keys
346
424
 
347
- Merges deeply nested hashes together while mutating itself.
425
+ Converts keys to strings without mutating itself.
348
426
 
349
427
  [source,ruby]
350
428
  ----
351
- example = {a: "A", b: {one: "One", two: "Two"}}
352
- example.deep_merge! b: {one: 1} # => {a: "A", b: {one: 1, two: "Two"}}
353
- example # => {a: "A", b: {one: 1, two: "Two"}}
429
+ example = {a: 1, b: 2}
430
+ example.stringify_keys # => {"a" => 1, "b" => 2}
431
+ example # => {a: 1, b: 2}
354
432
  ----
355
433
 
356
- ===== #deep_stringify_keys
434
+ ===== #stringify_keys!
357
435
 
358
- Stringifies keys of nested hash without mutating itself. Does not handle nested arrays, though.
436
+ Converts keys to strings while mutating itself.
359
437
 
360
438
  [source,ruby]
361
439
  ----
362
- example = {a: {b: 2}}
363
- example.deep_stringify_keys # => {"a" => {"b" => 1}}
364
- example # => {a: {b: 2}}
440
+ example = {a: 1, b: 2}
441
+ example.stringify_keys! # => {"a" => 1, "b" => 2}
442
+ example # => {"a" => 1, "b" => 2}
365
443
  ----
366
444
 
367
- ===== #deep_stringify_keys!
445
+ ===== #symbolize_keys
368
446
 
369
- Stringifies keys of nested hash while mutating itself. Does not handle nested arrays, though.
447
+ Converts keys to symbols without mutating itself.
370
448
 
371
449
  [source,ruby]
372
450
  ----
373
- example = {a: {b: 2}}
374
- example.deep_stringify_keys! # => {"a" => {"b" => 1}}
375
- example # => {"a" => {"b" => 1}}
451
+ example = {"a" => 1, "b" => 2}
452
+ example.symbolize_keys # => {a: 1, b: 2}
453
+ example # => {"a" => 1, "b" => 2}
376
454
  ----
377
455
 
378
- ===== #deep_symbolize_keys
456
+ ===== #symbolize_keys!
379
457
 
380
- Symbolizes keys of nested hash without mutating itself. Does not handle nested arrays, though.
458
+ Converts keys to symbols while mutating itself.
381
459
 
382
460
  [source,ruby]
383
461
  ----
384
- example = {"a" => {"b" => 2}}
385
- example.deep_symbolize_keys # => {a: {b: 1}}
386
- example # => {"a" => {"b" => 2}}
462
+ example = {"a" => 1, "b" => 2}
463
+ example.symbolize_keys! # => {a: 1, b: 2}
464
+ example # => {a: 1, b: 2}
387
465
  ----
388
466
 
389
- ===== #deep_symbolize_keys!
467
+ ===== #use
390
468
 
391
- Symbolizes keys of nested hash while mutating itself. Does not handle nested arrays, though.
469
+ Passes each hash value as a block argument for further processing.
392
470
 
393
471
  [source,ruby]
394
472
  ----
395
- example = {"a" => {"b" => 2}}
396
- example.deep_symbolize_keys! # => {a: {b: 1}}
397
- example # => {a: {b: 1}}
473
+ example = {unit: "221B", street: "Baker Street", city: "London", country: "UK"}
474
+ example.use { |unit, street| "#{unit} #{street}" } # => "221B Baker Street"
398
475
  ----
399
476
 
400
- ===== #recurse
401
-
402
- Recursively iterates over the hash and any hash value by applying the given block to it. Does not
403
- handle nested arrays, though.
404
-
405
- [source,ruby]
406
- ----
407
- example = {"a" => {"b" => 1}}
408
- example.recurse(&:symbolize_keys) # => {a: {b: 1}}
409
- example.recurse(&:invert) # => {{"b" => 1} => "a"}
410
- ----
477
+ ==== IO
411
478
 
412
- ===== #rekey
479
+ ===== .void
413
480
 
414
- Transforms keys per mapping (size of mapping can vary) without mutating itself.
481
+ Answers an IO stream which points to `/dev/null` in order to ignore any reads or writes to the
482
+ stream. When given a block, the stream will automatically close upon block exit. When not given a
483
+ block, you'll need to close the stream manually.
415
484
 
416
485
  [source,ruby]
417
486
  ----
418
- example = {a: 1, b: 2, c: 3}
419
- example.rekey a: :amber, b: :blue # => {amber: 1, blue: 2, c: 3}
420
- example # => {a: 1, b: 2, c: 3}
487
+ io = IO.void # => #<IO:fd 20>
488
+ io = IO.void { |void| void.write "nevermore" } # => #<IO:(closed)>
421
489
  ----
422
490
 
423
- ===== #rekey!
491
+ ===== #redirect
424
492
 
425
- Transforms keys per mapping (size of mapping can vary) while mutating itself.
493
+ Redirects current stream to other stream when given a block. Without a block, the original stream is
494
+ answered instead.
426
495
 
427
496
  [source,ruby]
428
497
  ----
429
- example = {a: 1, b: 2, c: 3}
430
- example.rekey! a: :amber, b: :blue # => {amber: 1, blue: 2, c: 3}
431
- example # => {amber: 1, blue: 2, c: 3}
498
+ io = IO.new IO.sysopen(Pathname("test.txt").to_s, "w+")
499
+ other = IO.new IO.sysopen(Pathname("other.txt").to_s, "w+")
500
+
501
+ io.redirect other # => #<IO:fd 20>
502
+ io.redirect(other) { |stream| stream.write "test" } # => #<IO:fd 21>
432
503
  ----
433
504
 
434
- ===== #reverse_merge
505
+ ===== #reread
435
506
 
436
- Merges calling hash into passed in hash without mutating itself.
507
+ Answers full stream by rewinding to beginning of stream and reading all content.
437
508
 
438
509
  [source,ruby]
439
510
  ----
440
- example = {a: 1, b: 2}
441
- example.reverse_merge a: 0, c: 3 # => {a: 1, b: 2, c: 3}
442
- example # => {a: 1, b: 2}
443
- ----
444
-
445
- ===== #reverse_merge!
511
+ io = IO.new IO.sysopen(Pathname("test.txt").to_s, "w+")
512
+ io.write "This is a test."
446
513
 
447
- Merges calling hash into passed in hash while mutating itself.
514
+ io.reread # => "This is a test."
515
+ io.reread 4 # => "This"
448
516
 
449
- [source,ruby]
450
- ----
451
- example = {a: 1, b: 2}
452
- example.reverse_merge! a: 0, c: 3 # => {a: 1, b: 2, c: 3}
453
- example # => {a: 1, b: 2, c: 3}
517
+ buffer = "".dup
518
+ io.reread(buffer: buffer) # => "This is a test."
519
+ buffer # => "This is a test."
454
520
  ----
455
521
 
456
- ===== #use
522
+ ===== #squelch
457
523
 
458
- Passes each hash value as a block argument for further processing.
524
+ Temporarily ignores any reads/writes for code executed within a block. Answers itself without any
525
+ arguments or when given a block.
459
526
 
460
527
  [source,ruby]
461
528
  ----
462
- example = {unit: "221B", street: "Baker Street", city: "London", country: "UK"}
463
- example.use { |unit, street| "#{unit} #{street}" } # => "221B Baker Street"
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 # => ""
464
533
  ----
465
534
 
466
535
  ==== Pathname
467
536
 
468
537
  ===== Pathname
469
538
 
470
- Enhances the conversion function -- refined from `Kernel` -- which casts `nil` into a pathname in
471
- order to avoid: `TypeError (no implicit conversion of nil into String)`. The pathname is still
472
- invalid but at least you have an instance of `Pathname`, which behaves like a _Null Object_, that
473
- can still be used to construct a valid path.
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.
474
543
 
475
544
  [source,ruby]
476
545
  ----
477
546
  Pathname(nil) # => Pathname("")
478
547
  ----
479
548
 
480
- ===== #name
549
+ ===== #change_dir
481
550
 
482
- Answers file name without extension.
551
+ Inherits and wraps `Dir.chdir` behavior by changing to directory of current path. See
552
+ link:https://rubyapi.org/2.7/o/s?q=Dir.chdir[Dir.chdir] for details.
483
553
 
484
554
  [source,ruby]
485
555
  ----
486
- Pathname("example.txt").name # => Pathname("example")
556
+ Pathname.pwd # => "/"
557
+ Pathname("/test").make_dir.change_dir # => Pathname "/test"
558
+ Pathname.pwd # => "/test"
559
+
560
+ Pathname.pwd # => "/"
561
+ Pathname("/test").make_dir.change_dir { "example" } # => "example"
562
+ Pathname.pwd # => "/"
487
563
  ----
488
564
 
489
565
  ===== #copy
490
566
 
491
- Copies file from current location to new location.
567
+ Copies file from current location to new location while answering itself so it can be chained.
492
568
 
493
569
  [source,ruby]
494
570
  ----
495
- Pathname("input.txt").copy Pathname("output.txt")
571
+ Pathname("input.txt").copy Pathname("output.txt") # => Pathname("input.txt")
496
572
  ----
497
573
 
498
574
  ===== #directories
499
575
 
500
- Answers all or filtered directories for current path.
576
+ Answers all directories or filtered directories for current path.
501
577
 
502
578
  [source,ruby]
503
579
  ----
@@ -517,7 +593,7 @@ Pathname("example.txt.erb").extensions # => [".txt", ".erb"]
517
593
 
518
594
  ===== #files
519
595
 
520
- Answers all or filtered files for current path.
596
+ Answers all files or filtered files for current path.
521
597
 
522
598
  [source,ruby]
523
599
  ----
@@ -539,6 +615,48 @@ Pathname("/%placeholder%/some/%placeholder%").gsub("%placeholder%", "test")
539
615
  # => Pathname("/test/some/test")
540
616
  ----
541
617
 
618
+ ===== #make_ancestors
619
+
620
+ Ensures all ancestor directories are created for a path.
621
+
622
+ [source,ruby]
623
+ ----
624
+ Pathname("/one/two").make_ancestors # => Pathname("/one/two")
625
+ Pathname("/one").exist? # => true
626
+ Pathname("/one/two").exist? # => false
627
+ ----
628
+
629
+ ===== #make_dir
630
+
631
+ Provides alternative `#mkdir` behavior by always answering itself (even when directory exists) and
632
+ not throwing errors when directory does exist in order to ensure the pathname can be chained.
633
+
634
+ [source,ruby]
635
+ ----
636
+ Pathname("/one").make_dir # => Pathname("/one")
637
+ Pathname("/one").make_dir.make_dir # => Pathname("/one")
638
+ ----
639
+
640
+ ===== #make_path
641
+
642
+ Provides alternative `#mkpath` behavior by always answering itself (even when full path exists) and
643
+ not throwing errors when directory does exist in order to ensure the pathname can be chained.
644
+
645
+ [source,ruby]
646
+ ----
647
+ Pathname("/one/two/three").make_path # => Pathname("/one/two/three")
648
+ Pathname("/one/two/three").make_path.make_path # => Pathname("/one/two/three")
649
+ ----
650
+
651
+ ===== #name
652
+
653
+ Answers file name without extension.
654
+
655
+ [source,ruby]
656
+ ----
657
+ Pathname("example.txt").name # => Pathname("example")
658
+ ----
659
+
542
660
  ===== #relative_parent
543
661
 
544
662
  Answers relative path from parent directory. This is a complement to `#relative_path_from`.
@@ -548,59 +666,74 @@ Answers relative path from parent directory. This is a complement to `#relative_
548
666
  Pathname("/one/two/three").relative_parent("/one") # => Pathname "two"
549
667
  ----
550
668
 
551
- ===== #make_ancestors
669
+ ===== #remove_dir
552
670
 
553
- Ensures all ancestor directories are created for a path.
671
+ Provides alternative `#rmdir` behavior by always answering itself (even when full path exists) and
672
+ not throwing errors when directory does exist in order to ensure the pathname can be chained.
554
673
 
555
674
  [source,ruby]
556
675
  ----
557
- Pathname("/one/two").make_ancestors
558
- Pathname("/one").exist? # => true
559
- Pathname("/one/two").exist? # => false
676
+ Pathname("/test").make_dir.remove_dir.exist? # => false
677
+ Pathname("/test").remove_dir # => Pathname("/test")
678
+ Pathname("/test").remove_dir.remove_dir # => Pathname("/test")
560
679
  ----
561
680
 
562
- ===== #rewrite
681
+ ===== #remove_tree
563
682
 
564
- When given a block, it provides the contents of the recently read file for manipulation and
565
- immediate writing back to the same file.
683
+ Provides alternative `#rmtree` behavior by always answering itself (even when full path exists) and
684
+ not throwing errors when directory does exist in order to ensure the pathname can be chained.
566
685
 
567
686
  [source,ruby]
568
687
  ----
569
- Pathname("/test.txt").rewrite { |content| content.sub "[placeholder]", "example" }
688
+ parent_path = Pathname "/one"
689
+ child_path = parent_path.join "two"
690
+
691
+ child_path.make_path
692
+ child_path.remove_tree # => Pathname "/one/two"
693
+ child_path.exist? # => false
694
+ paremt_path.exist? # => true
695
+
696
+ child_path.make_path
697
+ parent_path.remove_tree # => Pathname "/one"
698
+ child_path.exist? # => false
699
+ parent_path.exist? # => false
570
700
  ----
571
701
 
572
- ===== #touch
702
+ ===== #rewrite
573
703
 
574
- Updates access and modification times for path. Defaults to current time.
704
+ When given a block, it provides the contents of the recently read file for manipulation and
705
+ immediate writing back to the same file.
575
706
 
576
707
  [source,ruby]
577
708
  ----
578
- Pathname("example.txt").touch
579
- Pathname("example.txt").touch at: Time.now - 1
709
+ Pathname("/test.txt").rewrite # => Pathname("/test.txt")
710
+ Pathname("/test.txt").rewrite { |body| body.sub "[token]", "example" } # => Pathname("/test.txt")
580
711
  ----
581
712
 
582
- ==== String
583
-
584
- ===== #first
713
+ ===== #touch
585
714
 
586
- Answers first character of a string or first set of characters if given a number.
715
+ Updates access and modification times for path. Defaults to current time.
587
716
 
588
717
  [source,ruby]
589
718
  ----
590
- "example".first # => "e"
591
- "example".first 4 # => "exam"
719
+ Pathname("example.txt").touch # => Pathname("example.txt")
720
+ Pathname("example.txt").touch at: Time.now - 1 # => Pathname("example.txt")
592
721
  ----
593
722
 
594
- ===== #last
723
+ ===== #write
595
724
 
596
- Answers last character of a string or last set of characters if given a number.
725
+ Writes to file and answers itself so it can be chained. See `IO.write` for details on additional
726
+ options.
597
727
 
598
728
  [source,ruby]
599
729
  ----
600
- "instant".last # => "t"
601
- "instant".last 3 # => "ant"
730
+ Pathname("example.txt").write "test" # => Pathname("example.txt")
731
+ Pathname("example.txt").write "test", offset: 1 # => Pathname("example.txt")
732
+ Pathname("example.txt").write "test", mode: "a" # => Pathname("example.txt")
602
733
  ----
603
734
 
735
+ ==== String
736
+
604
737
  ===== #blank?
605
738
 
606
739
  Answers `true`/`false` based on whether string is blank, `<space>`, `\n`, `\t`, and/or `\r`.
@@ -610,13 +743,13 @@ Answers `true`/`false` based on whether string is blank, `<space>`, `\n`, `\t`,
610
743
  " \n\t\r".blank? # => true
611
744
  ----
612
745
 
613
- ===== #up
746
+ ===== #camelcase
614
747
 
615
- Answers string with only first letter upcased.
748
+ Answers a camelcased string.
616
749
 
617
750
  [source,ruby]
618
751
  ----
619
- "example".up # => "Example"
752
+ "this_is_an_example".camelcase # => "ThisIsAnExample"
620
753
  ----
621
754
 
622
755
  ===== #down
@@ -628,6 +761,16 @@ Answers string with only first letter downcased.
628
761
  "EXAMPLE".down # => "eXAMPLE"
629
762
  ----
630
763
 
764
+ ===== #first
765
+
766
+ Answers first character of a string or first set of characters if given a number.
767
+
768
+ [source,ruby]
769
+ ----
770
+ "example".first # => "e"
771
+ "example".first 4 # => "exam"
772
+ ----
773
+
631
774
  ===== #indent
632
775
 
633
776
  Answers string indented by two spaces by default.
@@ -641,13 +784,14 @@ Answers string indented by two spaces by default.
641
784
  "example".indent 3, padding: " " # => " example"
642
785
  ----
643
786
 
644
- ===== #camelcase
787
+ ===== #last
645
788
 
646
- Answers a camelcased string.
789
+ Answers last character of a string or last set of characters if given a number.
647
790
 
648
791
  [source,ruby]
649
792
  ----
650
- "this_is_an_example".camelcase # => "ThisIsAnExample"
793
+ "instant".last # => "t"
794
+ "instant".last 3 # => "ant"
651
795
  ----
652
796
 
653
797
  ===== #snakecase
@@ -681,6 +825,15 @@ Answers string as a boolean.
681
825
  "example".to_bool # => false
682
826
  ----
683
827
 
828
+ ===== #up
829
+
830
+ Answers string with only first letter upcased.
831
+
832
+ [source,ruby]
833
+ ----
834
+ "example".up # => "Example"
835
+ ----
836
+
684
837
  ==== String IO
685
838
 
686
839
  ===== #reread
@@ -696,8 +849,70 @@ io.reread # => "This is a test."
696
849
  io.reread 4 # => "This"
697
850
 
698
851
  buffer = "".dup
699
- io.reread(buffer: buffer)
700
- buffer # => "This is a test."
852
+ io.reread(buffer: buffer) # => "This is a test."
853
+ buffer # => "This is a test."
854
+ ----
855
+
856
+ ==== Struct
857
+
858
+ ===== #merge
859
+
860
+ Merges multiple attributes without mutating itself.
861
+
862
+ [source,ruby]
863
+ ----
864
+ Example = Struct.new :a, :b, :c
865
+ example = Example[1, 2, 3]
866
+ example.merge a: 10 # => #<struct a=10, b=2, c=3>
867
+ example.merge a: 10, c: 30 # => #<struct a=10, b=2, c=30>
868
+ example.merge a: 10, b: 20, c: 30 # => #<struct a=10, b=20, c=30>
869
+ example # => #<struct a=1, b=2, c=3>
870
+
871
+ Example = Struct.new :a, :b, :c, keyword_init: true
872
+ example = Example[a: 1, b: 2, c: 3]
873
+ example.merge a: 10 # => #<struct a=10, b=2, c=3>
874
+ example.merge a: 10, c: 30 # => #<struct a=10, b=2, c=30>
875
+ example.merge a: 10, b: 20, c: 30 # => #<struct a=10, b=20, c=30>
876
+ example # => #<struct a=1, b=2, c=3>
877
+ ----
878
+
879
+ ===== #merge!
880
+
881
+ Merges multiple attributes while mutating itself.
882
+
883
+ [source,ruby]
884
+ ----
885
+ Example = Struct.new :a, :b, :c
886
+ example = Example[1, 2, 3]
887
+ example.merge! a: 10 # => #<struct a=10, b=2, c=3>
888
+ example.merge! a: 10, c: 30 # => #<struct a=10, b=2, c=30>
889
+ example.merge! a: 10, b: 20, c: 30 # => #<struct a=10, b=20, c=30>
890
+ example # => #<struct a=10, b=20, c=30>
891
+
892
+ Example = Struct.new :a, :b, :c, keyword_init: true
893
+ example = Example[a: 1, b: 2, c: 3]
894
+ example.merge! a: 10 # => #<struct a=10, b=2, c=3>
895
+ example.merge! a: 10, c: 30 # => #<struct a=10, b=2, c=30>
896
+ example.merge! a: 10, b: 20, c: 30 # => #<struct a=10, b=20, c=30>
897
+ example # => #<struct a=10, b=20, c=30>
898
+ ----
899
+
900
+ == Development
901
+
902
+ To contribute, run:
903
+
904
+ [source,bash]
905
+ ----
906
+ git clone https://github.com/bkuhlmann/refinements.git
907
+ cd refinements
908
+ bin/setup
909
+ ----
910
+
911
+ You can also use the IRB console for direct access to all objects:
912
+
913
+ [source,bash]
914
+ ----
915
+ bin/console
701
916
  ----
702
917
 
703
918
  == Tests