refinements 7.12.0 → 7.16.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3df95fcb46ec44d2945b1eb3ab7dafd8ba6bb243973829d662e448ef74695302
4
- data.tar.gz: 21d89890312770ec2c73387c05c44dc31b22de849e18c3db6b4248476ca8bbdf
3
+ metadata.gz: 27c7f3818bd1f3d0d3fc39cb4c8721097d5003176b54710888deba6d012b4f77
4
+ data.tar.gz: f607fea47fce94c11c3ab7dcc6603b169567133fbbe6ca76fb0af0c9fa0196e4
5
5
  SHA512:
6
- metadata.gz: d0cb8fa10183e03737eab0ae1780b91e2e4ce994fd0945c7e2653bacd852dae85de474a073f4b1f6b8634e685059a54a0651b46ec567defd283cfb1491988e50
7
- data.tar.gz: a3f2ea6940f0e8c74f41f43d28d34a71892d3ddcaaf295c64ce4761b120421f80c7833bd9b48d37a90e485c3b606c38adb71e8665cf9feecad35925da485628a
6
+ metadata.gz: da5ff60dc1e6d4055adc850bbe7aa48d02c148f17fb42c9e50f939d577d506097603c2790cf5ce040cce1cb8389e28ebd363d3318d1224d06df4fc6d36e56b3f
7
+ data.tar.gz: a5a96d51b0e95d1f603262ca8ce767969e3faca18645327f368d8ee03aed7d0fa27211d9e35a8af30bcc6ca86d6dad33d804a4c9f1b830789b39b06dc0791793
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -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
- ===== #include
131
+ ===== #excluding
127
132
 
128
- Adds given array or elements without mutating itself.
133
+ Removes given array or elements without mutating itself.
129
134
 
130
135
  [source,ruby]
131
136
  ----
132
- [1, 2, 3].include [4, 5] # => [1, 2, 3, 4, 5]
133
- [1, 2, 3].include 4, 5 # => [1, 2, 3, 4, 5]
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
- ===== #intersperse
141
+ ===== #including
137
142
 
138
- Inserts additional elements or array between all members of given array.
143
+ Adds given array or elements without mutating itself.
139
144
 
140
145
  [source,ruby]
141
146
  ----
142
- [1, 2, 3].intersperse :a # => [1, :a, 2, :a, 3]
143
- [1, 2, 3].intersperse :a, :b # => [1, :a, :b, 2, :a, :b, 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
- ===== #exclude
151
+ ===== #intersperse
148
152
 
149
- Removes given array or elements without mutating itself.
153
+ Inserts additional elements or array between all members of given array.
150
154
 
151
155
  [source,ruby]
152
156
  ----
153
- [1, 2, 3, 4, 5].exclude [4, 5] # => [1, 2, 3]
154
- [1, 2, 3, 4, 5].exclude 4, 5 # => [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}" } # => "221B Baker 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.closed? # => false
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 # => `io`
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 # => "This is a test."
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 conversion function -- refined from `Kernel` -- which casts `nil` into a pathname in
540
- order to avoid: `TypeError (no implicit conversion of nil into String)`. The pathname is still
541
- invalid but at least you have an instance of `Pathname`, which behaves like a _Null Object_, that
542
- 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.
543
543
 
544
544
  [source,ruby]
545
545
  ----
546
546
  Pathname(nil) # => Pathname("")
547
547
  ----
548
548
 
549
- ===== #name
549
+ ===== .home
550
550
 
551
- Answers file name without extension.
551
+ Answers user home directory.
552
552
 
553
553
  [source,ruby]
554
554
  ----
555
- Pathname("example.txt").name # => Pathname("example")
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 # => [".txt", ".erb"]
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
- ===== #make_ancestors
738
+ ===== #remove_dir
621
739
 
622
- Ensures all ancestor directories are created for a path.
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("/one/two").make_ancestors
627
- Pathname("/one").exist? # => true
628
- Pathname("/one/two").exist? # => false
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
- ===== #mkdir
750
+ ===== #remove_tree
632
751
 
633
- Modifies default behavior by always answering itself (even when directory exists) and not throwing
634
- errors when directory exists.
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
- Pathname("/one").mkdir # => Pathname("/one")
639
- Pathname("/one").mkdir.mkdir # => Pathname("/one")
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 { |content| content.sub "[placeholder]", "example" }
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
- ==== String
792
+ ===== #write
663
793
 
664
- ===== #first
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".first # => "e"
671
- "example".first 4 # => "exam"
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
- ===== #last
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
- ===== #up
815
+ ===== #camelcase
694
816
 
695
- Answers string with only first letter upcased.
817
+ Answers a camelcased string.
696
818
 
697
819
  [source,ruby]
698
820
  ----
699
- "example".up # => "Example"
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
- ===== #camelcase
856
+ ===== #last
725
857
 
726
- Answers a camelcased string.
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
- "this_is_an_example".camelcase # => "ThisIsAnExample"
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 # => "This is a test."
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
@@ -10,3 +10,4 @@ require "refinements/ios"
10
10
  require "refinements/pathnames"
11
11
  require "refinements/strings"
12
12
  require "refinements/string_ios"
13
+ require "refinements/structs"
@@ -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
@@ -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 block_given?
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 block_given?
122
+ return [] unless block
123
123
 
124
124
  block.parameters
125
125
  .map { |(_type, key)| self[key] }
@@ -5,7 +5,7 @@ module Refinements
5
5
  module Identity
6
6
  NAME = "refinements"
7
7
  LABEL = "Refinements"
8
- VERSION = "7.12.0"
8
+ VERSION = "7.16.0"
9
9
  VERSION_LABEL = "#{LABEL} #{VERSION}"
10
10
  end
11
11
  end
@@ -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 name
17
- basename extname
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 make_ancestors
53
- dirname.mkpath
54
- self
92
+ def remove_dir
93
+ exist? ? (rmdir and self) : self
55
94
  end
56
95
 
57
- # rubocop:disable Style/RedundantSelf
58
- def mkdir
59
- self.exist? ? self : super and 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
@@ -12,42 +12,33 @@ module Refinements
12
12
  end
13
13
 
14
14
  refine String do
15
- def first number = 0
16
- return self if empty?
17
-
18
- max = Integer number
15
+ def blank?
16
+ match?(/\A\s*\z/)
17
+ end
19
18
 
20
- return self[0] if max.zero?
21
- return "" if max.negative?
19
+ def camelcase
20
+ return up unless match? DELIMITERS
22
21
 
23
- self[..(max - 1)]
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 last number = 0
27
+ def down
27
28
  return self if empty?
28
29
 
29
- min = Integer number
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 up
33
+ def first number = 0
42
34
  return self if empty?
43
35
 
44
- first.upcase + self[1, size]
45
- end
36
+ max = Integer number
46
37
 
47
- def down
48
- return self if empty?
38
+ return self[0] if max.zero?
39
+ return "" if max.negative?
49
40
 
50
- first.downcase + self[1, size]
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 camelcase
60
- return up unless match? DELIMITERS
50
+ def last number = 0
51
+ return self if empty?
61
52
 
62
- split(%r(\s*-\s*|\s*/\s*|\s*:+\s*)).then { |parts| combine parts, :up, "::" }
63
- .then { |text| text.split(/\s*_\s*|\s+/) }
64
- .then { |parts| combine parts, :up }
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.12.0
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-04 00:00:00.000000000 Z
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.6'
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.6'
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.2'
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.2'
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.0'
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.0'
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.9'
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.9'
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: '0.89'
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: '0.89'
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.5'
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.5'
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: '1.39'
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: '1.39'
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