refinements 7.9.0 → 7.14.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: ba7c2934d38986ae19d3a41bdc1305164ebe2355bb30afa925eebbeb9746f962
4
- data.tar.gz: 1945d2226c6ca304aa9958635aab6a87880b66e43566691c3ab509f5b2e77f6b
3
+ metadata.gz: 4abbbd79616d97836ca58503bb4638e2638e14732e76e7c00b3f5c033f708edc
4
+ data.tar.gz: 516c79b5361a7512ca4e63c72303d8fb0d2cb85c693bc9aa13c36ef767580f10
5
5
  SHA512:
6
- metadata.gz: 34e601f3bfe0ebe6b35ddf54dea67ef9c33d7436fae5103a2ce03106a34026f1920a6f06369ba2516ceb0a550bb6868fcd5491084cca5b6dd20ed746b4772a39
7
- data.tar.gz: 8e4d5de5f29f28df044333dbaa34fb0a6d9b34911e3e911bd5593caf4dfeb52c0c0767f5a01d164542c54a4d936453b14f6131c055234a5911d73c80673c7d14
6
+ metadata.gz: 2f15aa4b466d6e610a2ffc45ad16285d27107c93a4260d214abcee42e66005951a5f2a708da6b04a28826ab3abd0a85ad0e1a707782b6ba5c51ef5cb0b705ec7
7
+ data.tar.gz: ec214191217bb870ca264fbfe3fa31d57b6c37c28e0f92806f779d3ea8400fbac11ee4aa38c82d6d10d7b07187a2360a7aa810ef802e6d219a217043cd76e69c
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,10 +6,12 @@
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
 
12
- A collection of refinements (enhancements) to core Ruby objects.
14
+ A collection of refinements (enhancements) to primitive Ruby objects.
13
15
 
14
16
  toc::[]
15
17
 
@@ -22,6 +24,7 @@ Enhances the following objects:
22
24
  * DateTime
23
25
  * File
24
26
  * Hash
27
+ * IO
25
28
  * Pathname
26
29
  * String
27
30
  * StringIO
@@ -34,8 +37,6 @@ Enhances the following objects:
34
37
 
35
38
  == Setup
36
39
 
37
- === Production
38
-
39
40
  To install, run:
40
41
 
41
42
  [source,bash]
@@ -50,24 +51,6 @@ Add the following to your Gemfile file:
50
51
  gem "refinements"
51
52
  ----
52
53
 
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
54
  == Usage
72
55
 
73
56
  === Requires
@@ -79,7 +62,7 @@ If all refinements are not desired, add the following to your `+Gemfile+` instea
79
62
  gem "refinements", require: false
80
63
  ----
81
64
 
82
- then require the specific refinement, as needed. Example:
65
+ ...then require the specific refinement, as needed. Example:
83
66
 
84
67
  [source,ruby]
85
68
  ----
@@ -88,6 +71,7 @@ require "refinements/big_decimals"
88
71
  require "refinements/date_times"
89
72
  require "refinements/files"
90
73
  require "refinements/hashes"
74
+ require "refinements/ios"
91
75
  require "refinements/pathnames"
92
76
  require "refinements/strings"
93
77
  require "refinements/string_ios"
@@ -95,7 +79,8 @@ require "refinements/string_ios"
95
79
 
96
80
  === Using
97
81
 
98
- Much like including/extending a module, you’ll need modify your object(s) to use the refinement(s):
82
+ Much like including/extending a module, you’ll need to modify your object(s) to use the
83
+ refinement(s):
99
84
 
100
85
  [source,ruby]
101
86
  ----
@@ -105,6 +90,7 @@ class Example
105
90
  using Refinements::DateTimes
106
91
  using Refinements::Files
107
92
  using Refinements::Hashes
93
+ using Refinements::IOs
108
94
  using Refinements::Pathnames
109
95
  using Refinements::Strings
110
96
  using Refinements::StringIOs
@@ -119,7 +105,7 @@ The following sections demonstrate how each refinement enriches your objects wit
119
105
 
120
106
  ===== #compress
121
107
 
122
- Removes `nil` and empty values without modifying itself.
108
+ Removes `nil` and empty values without mutating itself.
123
109
 
124
110
  [source,ruby]
125
111
  ----
@@ -130,7 +116,7 @@ example # => ["An", nil, "", "Example"]
130
116
 
131
117
  ===== #compress!
132
118
 
133
- Removes `nil` and empty values while modifying itself.
119
+ Removes `nil` and empty values while mutating itself.
134
120
 
135
121
  [source,ruby]
136
122
  ----
@@ -139,24 +125,47 @@ example.compress! # => ["An", "Example"]
139
125
  example # => ["An", "Example"]
140
126
  ----
141
127
 
142
- ===== #include
128
+ ===== #excluding
129
+
130
+ Removes given array or elements without mutating itself.
131
+
132
+ [source,ruby]
133
+ ----
134
+ [1, 2, 3, 4, 5].excluding [4, 5] # => [1, 2, 3]
135
+ [1, 2, 3, 4, 5].excluding 4, 5 # => [1, 2, 3]
136
+ ----
137
+
138
+ ===== #including
143
139
 
144
- Adds given array or elements without modifying itself.
140
+ Adds given array or elements without mutating itself.
145
141
 
146
142
  [source,ruby]
147
143
  ----
148
- [1, 2, 3].include [4, 5] # => [1, 2, 3, 4, 5]
149
- [1, 2, 3].include 4, 5 # => [1, 2, 3, 4, 5]
144
+ [1, 2, 3].including [4, 5] # => [1, 2, 3, 4, 5]
145
+ [1, 2, 3].including 4, 5 # => [1, 2, 3, 4, 5]
150
146
  ----
151
147
 
152
- ===== #exclude
148
+ ===== #intersperse
153
149
 
154
- Removes given array or elements without modifying itself.
150
+ Inserts additional elements or array between all members of given array.
155
151
 
156
152
  [source,ruby]
157
153
  ----
158
- [1, 2, 3, 4, 5].exclude [4, 5] # => [1, 2, 3]
159
- [1, 2, 3, 4, 5].exclude 4, 5 # => [1, 2, 3]
154
+ [1, 2, 3].intersperse :a # => [1, :a, 2, :a, 3]
155
+ [1, 2, 3].intersperse :a, :b # => [1, :a, :b, 2, :a, :b, 3]
156
+ [1, 2, 3].intersperse %i[a b c] # => [1, :a, :b, :c, 2, :a, :b, :c, 3]
157
+ ----
158
+
159
+ ===== #mean
160
+
161
+ Answers mean/average all elements within an array.
162
+
163
+ [source,ruby]
164
+ ----
165
+ [].mean # => 0
166
+ [5].mean # => 5
167
+ [1, 2, 3].mean # => 2
168
+ [1.25, 1.5, 1.75].mean # => 1.5
160
169
  ----
161
170
 
162
171
  ===== #ring
@@ -234,127 +243,128 @@ example = Hash.with_default []
234
243
  example[:b] # => []
235
244
  ----
236
245
 
237
- ===== #except
246
+ ===== #deep_merge
238
247
 
239
- Answers new hash with given keys removed without modifying itself.
248
+ Merges deeply nested hashes together without mutating itself.
240
249
 
241
250
  [source,ruby]
242
251
  ----
243
- example = {a: 1, b: 2, c: 3}
244
- example.except :a, :b # => {c: 3}
245
- example # => {a: 1, b: 2, c: 3}
252
+ example = {a: "A", b: {one: "One", two: "Two"}}
253
+ example.deep_merge b: {one: 1} # => {a: "A", b: {one: 1, two: "Two"}}
254
+ example # => {a: "A", b: {one: "One", two: "Two"}}
246
255
  ----
247
256
 
248
- ===== #except!
257
+ ===== #deep_merge!
249
258
 
250
- Answers new hash with given keys removed while modifying itself.
259
+ Merges deeply nested hashes together while mutating itself.
251
260
 
252
261
  [source,ruby]
253
262
  ----
254
- example = {a: 1, b: 2, c: 3}
255
- example.except! :a, :b # => {c: 3}
256
- example # => {c: 3}
263
+ example = {a: "A", b: {one: "One", two: "Two"}}
264
+ example.deep_merge! b: {one: 1} # => {a: "A", b: {one: 1, two: "Two"}}
265
+ example # => {a: "A", b: {one: 1, two: "Two"}}
257
266
  ----
258
267
 
259
- ===== #flatten_keys
268
+ ===== #deep_stringify_keys
260
269
 
261
- Flattens nested keys as top-level keys without modifying itself. Does not handle nested arrays,
262
- though.
270
+ Stringifies keys of nested hash without mutating itself. Does not handle nested arrays, though.
263
271
 
264
272
  [source,ruby]
265
273
  ----
266
- {a: {b: 1}}.flatten_keys prefix: :test # => {test_a_b: 1}
267
- {a: {b: 1}}.flatten_keys delimiter: :| # => {:"a|b" => 1}
268
-
269
- {a: {b: 1}}.flatten_keys cast: :to_s # => {"a_b" => 1}
270
- {"a" => {"b" => 1}}.flatten_keys cast: :to_sym # => {a_b: 1}
271
-
272
- example = {a: {b: 1}}
273
- example.flatten_keys # => {a_b: 1}
274
- example # => {a: {b: 1}}
274
+ example = {a: {b: 2}}
275
+ example.deep_stringify_keys # => {"a" => {"b" => 1}}
276
+ example # => {a: {b: 2}}
275
277
  ----
276
278
 
277
- ===== #flatten_keys!
279
+ ===== #deep_stringify_keys!
278
280
 
279
- Flattens nested keys as top-level keys while modifying itself. Does not handle nested arrays,
280
- though.
281
+ Stringifies keys of nested hash while mutating itself. Does not handle nested arrays, though.
281
282
 
282
283
  [source,ruby]
283
284
  ----
284
- example = {a: {b: 1}}
285
- example.flatten_keys! # => {a_b: 1}
286
- example # => {a_b: 1}
285
+ example = {a: {b: 2}}
286
+ example.deep_stringify_keys! # => {"a" => {"b" => 1}}
287
+ example # => {"a" => {"b" => 1}}
287
288
  ----
288
289
 
289
- ===== #symbolize_keys
290
+ ===== #deep_symbolize_keys
290
291
 
291
- Converts keys to symbols without modifying itself.
292
+ Symbolizes keys of nested hash without mutating itself. Does not handle nested arrays, though.
292
293
 
293
294
  [source,ruby]
294
295
  ----
295
- example = {"a" => 1, "b" => 2}
296
- example.symbolize_keys # => {a: 1, b: 2}
297
- example # => {"a" => 1, "b" => 2}
296
+ example = {"a" => {"b" => 2}}
297
+ example.deep_symbolize_keys # => {a: {b: 1}}
298
+ example # => {"a" => {"b" => 2}}
298
299
  ----
299
300
 
300
- ===== #symbolize_keys!
301
+ ===== #deep_symbolize_keys!
301
302
 
302
- Converts keys to symbols while modifying itself.
303
+ Symbolizes keys of nested hash while mutating itself. Does not handle nested arrays, though.
303
304
 
304
305
  [source,ruby]
305
306
  ----
306
- example = {"a" => 1, "b" => 2}
307
- example.symbolize_keys! # => {a: 1, b: 2}
308
- example # => {a: 1, b: 2}
307
+ example = {"a" => {"b" => 2}}
308
+ example.deep_symbolize_keys! # => {a: {b: 1}}
309
+ example # => {a: {b: 1}}
309
310
  ----
310
311
 
311
- ===== #deep_merge
312
+ ===== #except
312
313
 
313
- Merges deeply nested hashes together without modifying itself.
314
+ Answers new hash with given keys removed without mutating itself.
314
315
 
315
316
  [source,ruby]
316
317
  ----
317
- example = {a: "A", b: {one: "One", two: "Two"}}
318
- example.deep_merge b: {one: 1} # => {a: "A", b: {one: 1, two: "Two"}}
319
- example # => {a: "A", b: {one: "One", two: "Two"}}
318
+ example = {a: 1, b: 2, c: 3}
319
+ example.except :a, :b # => {c: 3}
320
+ example # => {a: 1, b: 2, c: 3}
320
321
  ----
321
322
 
322
- ===== #deep_merge!
323
+ ===== #except!
323
324
 
324
- Merges deeply nested hashes together while modifying itself.
325
+ Answers new hash with given keys removed while mutating itself.
325
326
 
326
327
  [source,ruby]
327
328
  ----
328
- example = {a: "A", b: {one: "One", two: "Two"}}
329
- example.deep_merge! b: {one: 1} # => {a: "A", b: {one: 1, two: "Two"}}
330
- example # => {a: "A", b: {one: 1, two: "Two"}}
329
+ example = {a: 1, b: 2, c: 3}
330
+ example.except! :a, :b # => {c: 3}
331
+ example # => {c: 3}
331
332
  ----
332
333
 
333
- ===== #deep_symbolize_keys
334
+ ===== #flatten_keys
334
335
 
335
- Symbolizes keys of nested hash without modifying itself. Does not handle nested arrays, though.
336
+ Flattens nested keys as top-level keys without mutating itself. Does not handle nested arrays,
337
+ though.
336
338
 
337
339
  [source,ruby]
338
340
  ----
339
- example = {"a" => {"b" => 2}}
340
- example.deep_symbolize_keys # => {a: {b: 1}}
341
- example # => {"a" => {"b" => 2}}
341
+ {a: {b: 1}}.flatten_keys prefix: :test # => {test_a_b: 1}
342
+ {a: {b: 1}}.flatten_keys delimiter: :| # => {:"a|b" => 1}
343
+
344
+ {a: {b: 1}}.flatten_keys cast: :to_s # => {"a_b" => 1}
345
+ {"a" => {"b" => 1}}.flatten_keys cast: :to_sym # => {a_b: 1}
346
+
347
+ example = {a: {b: 1}}
348
+ example.flatten_keys # => {a_b: 1}
349
+ example # => {a: {b: 1}}
342
350
  ----
343
351
 
344
- ===== #deep_symbolize_keys!
352
+ ===== #flatten_keys!
345
353
 
346
- Symbolizes keys of nested hash while modifying itself. Does not handle nested arrays, though.
354
+ Flattens nested keys as top-level keys while mutating itself. Does not handle nested arrays,
355
+ though.
347
356
 
348
357
  [source,ruby]
349
358
  ----
350
- example = {"a" => {"b" => 2}}
351
- example.deep_symbolize_keys! # => {a: {b: 1}}
352
- example # => {a: {b: 1}}
359
+ example = {a: {b: 1}}
360
+ example.flatten_keys! # => {a_b: 1}
361
+ example # => {a_b: 1}
353
362
  ----
354
363
 
355
364
  ===== #recurse
356
365
 
357
- Applies block to nested hash. Does not handle nested arrays, though.
366
+ Recursively iterates over the hash and any hash value by applying the given block to it. Does not
367
+ handle nested arrays, though.
358
368
 
359
369
  [source,ruby]
360
370
  ----
@@ -365,7 +375,7 @@ example.recurse(&:invert) # => {{"b" => 1} => "a"}
365
375
 
366
376
  ===== #rekey
367
377
 
368
- Transforms keys per mapping (size of mapping can vary) without modifying itself.
378
+ Transforms keys per mapping (size of mapping can vary) without mutating itself.
369
379
 
370
380
  [source,ruby]
371
381
  ----
@@ -376,7 +386,7 @@ example # => {a: 1, b: 2, c: 3}
376
386
 
377
387
  ===== #rekey!
378
388
 
379
- Transforms keys per mapping (size of mapping can vary) while modifying itself.
389
+ Transforms keys per mapping (size of mapping can vary) while mutating itself.
380
390
 
381
391
  [source,ruby]
382
392
  ----
@@ -387,7 +397,7 @@ example # => {amber: 1, blue: 2, c: 3}
387
397
 
388
398
  ===== #reverse_merge
389
399
 
390
- Merges calling hash into passed in hash without modifying itself.
400
+ Merges calling hash into passed in hash without mutating itself.
391
401
 
392
402
  [source,ruby]
393
403
  ----
@@ -398,7 +408,7 @@ example # => {a: 1, b: 2}
398
408
 
399
409
  ===== #reverse_merge!
400
410
 
401
- Merges calling hash into passed in hash while modifying itself.
411
+ Merges calling hash into passed in hash while mutating itself.
402
412
 
403
413
  [source,ruby]
404
414
  ----
@@ -407,6 +417,50 @@ example.reverse_merge! a: 0, c: 3 # => {a: 1, b: 2, c: 3}
407
417
  example # => {a: 1, b: 2, c: 3}
408
418
  ----
409
419
 
420
+ ===== #stringify_keys
421
+
422
+ Converts keys to strings without mutating itself.
423
+
424
+ [source,ruby]
425
+ ----
426
+ example = {a: 1, b: 2}
427
+ example.stringify_keys # => {"a" => 1, "b" => 2}
428
+ example # => {a: 1, b: 2}
429
+ ----
430
+
431
+ ===== #stringify_keys!
432
+
433
+ Converts keys to strings while mutating itself.
434
+
435
+ [source,ruby]
436
+ ----
437
+ example = {a: 1, b: 2}
438
+ example.stringify_keys! # => {"a" => 1, "b" => 2}
439
+ example # => {"a" => 1, "b" => 2}
440
+ ----
441
+
442
+ ===== #symbolize_keys
443
+
444
+ Converts keys to symbols without mutating itself.
445
+
446
+ [source,ruby]
447
+ ----
448
+ example = {"a" => 1, "b" => 2}
449
+ example.symbolize_keys # => {a: 1, b: 2}
450
+ example # => {"a" => 1, "b" => 2}
451
+ ----
452
+
453
+ ===== #symbolize_keys!
454
+
455
+ Converts keys to symbols while mutating itself.
456
+
457
+ [source,ruby]
458
+ ----
459
+ example = {"a" => 1, "b" => 2}
460
+ example.symbolize_keys! # => {a: 1, b: 2}
461
+ example # => {a: 1, b: 2}
462
+ ----
463
+
410
464
  ===== #use
411
465
 
412
466
  Passes each hash value as a block argument for further processing.
@@ -417,24 +471,97 @@ example = {unit: "221B", street: "Baker Street", city: "London", country: "UK"}
417
471
  example.use { |unit, street| "#{unit} #{street}" } # => "221B Baker Street"
418
472
  ----
419
473
 
474
+ ==== IO
475
+
476
+ ===== .void
477
+
478
+ Answers an IO stream which points to `/dev/null` in order to ignore any reads or writes to the
479
+ stream. When given a block, the stream will automatically close upon block exit. When not given a
480
+ block, you'll need to close the stream manually.
481
+
482
+ [source,ruby]
483
+ ----
484
+ io = IO.void
485
+ io.closed? # => false
486
+
487
+ io = IO.void { |void| void.write "nevermore" }
488
+ io.closed? # => true
489
+ ----
490
+
491
+ ===== #redirect
492
+
493
+ Redirects current stream to other stream when given a block. Without a block, the original stream is
494
+ answered instead.
495
+
496
+ [source,ruby]
497
+ ----
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`
502
+
503
+ io.redirect(other) { |stream| stream.write "test" }
504
+ .close # => ""
505
+ other.close # => "test"
506
+ ----
507
+
508
+ ===== #reread
509
+
510
+ Answers full stream by rewinding to beginning of stream and reading all content.
511
+
512
+ [source,ruby]
513
+ ----
514
+ io = IO.new IO.sysopen(Pathname("test.txt").to_s, "w+")
515
+ io.write "This is a test."
516
+
517
+ io.reread # => "This is a test."
518
+ io.reread 4 # => "This"
519
+
520
+ buffer = "".dup
521
+ io.reread(buffer: buffer)
522
+ buffer # => "This is a test."
523
+ ----
524
+
525
+ ===== #squelch
526
+
527
+ Temporarily ignores any reads/writes for current stream for all code executed within the block. When
528
+ not given a block, it answers itself.
529
+
530
+ [source,ruby]
531
+ ----
532
+ io = IO.new IO.sysopen(Pathname("test.txt").to_s, "w+")
533
+ io.squelch { io.write "Test" }
534
+ io.reread # => ""
535
+ ----
536
+
420
537
  ==== Pathname
421
538
 
422
539
  ===== Pathname
423
540
 
424
- Conversion function (refined from `Kernel`) which can cast `nil` into a pathname.
541
+ Enhances the conversion function -- refined from `Kernel` -- which casts `nil` into a pathname in
542
+ order to avoid: `TypeError (no implicit conversion of nil into String)`. The pathname is still
543
+ invalid but at least you have an instance of `Pathname`, which behaves like a _Null Object_, that
544
+ can still be used to construct a valid path.
425
545
 
426
546
  [source,ruby]
427
547
  ----
428
548
  Pathname(nil) # => Pathname("")
429
549
  ----
430
550
 
431
- ===== #name
551
+ ===== #change_dir
432
552
 
433
- Answers file name without extension.
553
+ Inherits and wraps `Dir.chdir` behavior by changing to directory of current path. See
554
+ link:https://rubyapi.org/2.7/o/s?q=Dir.chdir[Dir.chdir] for details.
434
555
 
435
556
  [source,ruby]
436
557
  ----
437
- Pathname("example.txt").name # => Pathname("example")
558
+ Pathname.pwd # => "/"
559
+ Pathname("/test").make_dir.change_dir # => Pathname "/test"
560
+ Pathname.pwd # => "/test"
561
+
562
+ Pathname.pwd # => "/"
563
+ Pathname("/test").make_dir.change_dir { # Implementation details } # => Pathname "/test"
564
+ Pathname.pwd # => "/"
438
565
  ----
439
566
 
440
567
  ===== #copy
@@ -490,6 +617,48 @@ Pathname("/%placeholder%/some/%placeholder%").gsub("%placeholder%", "test")
490
617
  # => Pathname("/test/some/test")
491
618
  ----
492
619
 
620
+ ===== #make_ancestors
621
+
622
+ Ensures all ancestor directories are created for a path.
623
+
624
+ [source,ruby]
625
+ ----
626
+ Pathname("/one/two").make_ancestors
627
+ Pathname("/one").exist? # => true
628
+ Pathname("/one/two").exist? # => false
629
+ ----
630
+
631
+ ===== #make_dir
632
+
633
+ Provides alternative `#mkdir` behavior by always answering itself (even when directory exists) and
634
+ not throwing errors when directory does exist in order to ensure the pathname can be chained.
635
+
636
+ [source,ruby]
637
+ ----
638
+ Pathname("/one").make_dir # => Pathname("/one")
639
+ Pathname("/one").make_dir.make_dir # => Pathname("/one")
640
+ ----
641
+
642
+ ===== #make_path
643
+
644
+ Provides alternative `#mkpath` behavior by always answering itself (even when full path exists) and
645
+ not throwing errors when directory does exist in order to ensure the pathname can be chained.
646
+
647
+ [source,ruby]
648
+ ----
649
+ Pathname("/one/two/three").make_path # => Pathname("/one/two/three")
650
+ Pathname("/one/two/three").make_path.make_path # => Pathname("/one/two/three")
651
+ ----
652
+
653
+ ===== #name
654
+
655
+ Answers file name without extension.
656
+
657
+ [source,ruby]
658
+ ----
659
+ Pathname("example.txt").name # => Pathname("example")
660
+ ----
661
+
493
662
  ===== #relative_parent
494
663
 
495
664
  Answers relative path from parent directory. This is a complement to `#relative_path_from`.
@@ -499,15 +668,37 @@ Answers relative path from parent directory. This is a complement to `#relative_
499
668
  Pathname("/one/two/three").relative_parent("/one") # => Pathname "two"
500
669
  ----
501
670
 
502
- ===== #make_ancestors
671
+ ===== #remove_dir
503
672
 
504
- Ensures all ancestor directories are created for a path.
673
+ Provides alternative `#rmdir` behavior by always answering itself (even when full path exists) and
674
+ not throwing errors when directory does exist in order to ensure the pathname can be chained.
505
675
 
506
676
  [source,ruby]
507
677
  ----
508
- Pathname("/one/two").make_ancestors
509
- Pathname("/one").exist? # => true
510
- Pathname("/one/two").exist? # => false
678
+ Pathname("/test").make_dir.remove_dir.exist? # => false
679
+ Pathname("/test").remove_dir # => Pathname("/test")
680
+ Pathname("/test").remove_dir.remove_dir # => Pathname("/test")
681
+ ----
682
+
683
+ ===== #remove_tree
684
+
685
+ Provides alternative `#rmtree` behavior by always answering itself (even when full path exists) and
686
+ not throwing errors when directory does exist in order to ensure the pathname can be chained.
687
+
688
+ [source,ruby]
689
+ ----
690
+ parent_path = Pathname "/one"
691
+ child_path = parent_path.join "two"
692
+
693
+ child_path.make_path
694
+ child_path.remove_tree # => Pathname "/one/two"
695
+ child_path.exist? # => false
696
+ paremt_path.exist? # => true
697
+
698
+ child_path.make_path
699
+ parent_path.remove_tree # => Pathname "/one"
700
+ child_path.exist? # => false
701
+ parent_path.exist? # => false
511
702
  ----
512
703
 
513
704
  ===== #rewrite
@@ -532,60 +723,64 @@ Pathname("example.txt").touch at: Time.now - 1
532
723
 
533
724
  ==== String
534
725
 
535
- ===== #first
726
+ ===== #blank?
536
727
 
537
- Answers first character of a string or first set of characters if given a number.
728
+ Answers `true`/`false` based on whether string is blank, `<space>`, `\n`, `\t`, and/or `\r`.
538
729
 
539
730
  [source,ruby]
540
731
  ----
541
- "example".first # => "e"
542
- "example".first 4 # => "exam"
732
+ " \n\t\r".blank? # => true
543
733
  ----
544
734
 
545
- ===== #last
735
+ ===== #camelcase
546
736
 
547
- Answers last character of a string or last set of characters if given a number.
737
+ Answers a camelcased string.
548
738
 
549
739
  [source,ruby]
550
740
  ----
551
- "instant".last # => "t"
552
- "instant".last 3 # => "ant"
741
+ "this_is_an_example".camelcase # => "ThisIsAnExample"
553
742
  ----
554
743
 
555
- ===== #blank?
744
+ ===== #down
556
745
 
557
- Answers `true`/`false` based on whether string is blank, `<space>`, `\n`, `\t`, and/or `\r`.
746
+ Answers string with only first letter downcased.
558
747
 
559
748
  [source,ruby]
560
749
  ----
561
- " \n\t\r".blank? # => true
750
+ "EXAMPLE".down # => "eXAMPLE"
562
751
  ----
563
752
 
564
- ===== #up
753
+ ===== #first
565
754
 
566
- Answers string with only first letter upcased.
755
+ Answers first character of a string or first set of characters if given a number.
567
756
 
568
757
  [source,ruby]
569
758
  ----
570
- "example".up # => "Example"
759
+ "example".first # => "e"
760
+ "example".first 4 # => "exam"
571
761
  ----
572
762
 
573
- ===== #down
763
+ ===== #indent
574
764
 
575
- Answers string with only first letter downcased.
765
+ Answers string indented by two spaces by default.
576
766
 
577
767
  [source,ruby]
578
768
  ----
579
- "EXAMPLE".down # => "eXAMPLE"
769
+ "example".indent # => " example"
770
+ "example".indent 0 # => "example"
771
+ "example".indent -1 # => "example"
772
+ "example".indent 2 # => " example"
773
+ "example".indent 3, padding: " " # => " example"
580
774
  ----
581
775
 
582
- ===== #camelcase
776
+ ===== #last
583
777
 
584
- Answers a camelcased string.
778
+ Answers last character of a string or last set of characters if given a number.
585
779
 
586
780
  [source,ruby]
587
781
  ----
588
- "this_is_an_example".camelcase # => "ThisIsAnExample"
782
+ "instant".last # => "t"
783
+ "instant".last 3 # => "ant"
589
784
  ----
590
785
 
591
786
  ===== #snakecase
@@ -619,6 +814,15 @@ Answers string as a boolean.
619
814
  "example".to_bool # => false
620
815
  ----
621
816
 
817
+ ===== #up
818
+
819
+ Answers string with only first letter upcased.
820
+
821
+ [source,ruby]
822
+ ----
823
+ "example".up # => "Example"
824
+ ----
825
+
622
826
  ==== String IO
623
827
 
624
828
  ===== #reread
@@ -638,6 +842,24 @@ io.reread(buffer: buffer)
638
842
  buffer # => "This is a test."
639
843
  ----
640
844
 
845
+ == Development
846
+
847
+ To contribute, run:
848
+
849
+ [source,bash]
850
+ ----
851
+ git clone https://github.com/bkuhlmann/refinements.git
852
+ cd refinements
853
+ bin/setup
854
+ ----
855
+
856
+ You can also use the IRB console for direct access to all objects:
857
+
858
+ [source,bash]
859
+ ----
860
+ bin/console
861
+ ----
862
+
641
863
  == Tests
642
864
 
643
865
  To test, run:
@@ -6,6 +6,7 @@ require "refinements/big_decimals"
6
6
  require "refinements/date_times"
7
7
  require "refinements/files"
8
8
  require "refinements/hashes"
9
+ require "refinements/ios"
9
10
  require "refinements/pathnames"
10
11
  require "refinements/strings"
11
12
  require "refinements/string_ios"
@@ -11,12 +11,30 @@ 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
 
18
- def exclude *elements
19
- self - elements.flatten
32
+ def intersperse *elements
33
+ product([elements]).tap(&:pop).flatten.push last
34
+ end
35
+
36
+ def mean
37
+ size.zero? ? 0 : sum(0) / size
20
38
  end
21
39
 
22
40
  def ring &block
@@ -13,6 +13,38 @@ module Refinements
13
13
  end
14
14
 
15
15
  refine Hash do
16
+ def deep_merge other
17
+ clazz = self.class
18
+
19
+ merge other do |_key, this_value, other_value|
20
+ if this_value.is_a?(clazz) && other_value.is_a?(clazz)
21
+ this_value.deep_merge other_value
22
+ else
23
+ other_value
24
+ end
25
+ end
26
+ end
27
+
28
+ def deep_merge! other
29
+ replace deep_merge(other)
30
+ end
31
+
32
+ def deep_stringify_keys
33
+ recurse(&:stringify_keys)
34
+ end
35
+
36
+ def deep_stringify_keys!
37
+ replace deep_stringify_keys
38
+ end
39
+
40
+ def deep_symbolize_keys
41
+ recurse(&:symbolize_keys)
42
+ end
43
+
44
+ def deep_symbolize_keys!
45
+ replace deep_symbolize_keys
46
+ end
47
+
16
48
  def except *keys
17
49
  reject { |key, _value| keys.include? key }
18
50
  end
@@ -40,38 +72,6 @@ module Refinements
40
72
  replace flatten_keys(prefix: prefix, delimiter: delimiter, cast: cast)
41
73
  end
42
74
 
43
- def symbolize_keys
44
- reduce({}) { |hash, (key, value)| hash.merge key.to_sym => value }
45
- end
46
-
47
- def symbolize_keys!
48
- replace symbolize_keys
49
- end
50
-
51
- def deep_merge other
52
- clazz = self.class
53
-
54
- merge other do |_key, this_value, other_value|
55
- if this_value.is_a?(clazz) && other_value.is_a?(clazz)
56
- this_value.deep_merge other_value
57
- else
58
- other_value
59
- end
60
- end
61
- end
62
-
63
- def deep_merge! other
64
- replace deep_merge(other)
65
- end
66
-
67
- def deep_symbolize_keys
68
- recurse(&:symbolize_keys)
69
- end
70
-
71
- def deep_symbolize_keys!
72
- replace deep_symbolize_keys
73
- end
74
-
75
75
  def recurse &block
76
76
  return self unless block_given?
77
77
 
@@ -102,6 +102,22 @@ module Refinements
102
102
  replace reverse_merge(other)
103
103
  end
104
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
+
105
121
  def use &block
106
122
  return [] unless block_given?
107
123
 
@@ -5,7 +5,7 @@ module Refinements
5
5
  module Identity
6
6
  NAME = "refinements"
7
7
  LABEL = "Refinements"
8
- VERSION = "7.9.0"
8
+ VERSION = "7.14.0"
9
9
  VERSION_LABEL = "#{LABEL} #{VERSION}"
10
10
  end
11
11
  end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Refinements
4
+ module IOs
5
+ refine IO.singleton_class do
6
+ def void
7
+ new(sysopen("/dev/null", "w+")).then do |io|
8
+ return io unless block_given?
9
+
10
+ yield io
11
+ io.tap(&:close)
12
+ end
13
+ end
14
+ end
15
+
16
+ refine IO do
17
+ def redirect other
18
+ return self unless block_given?
19
+
20
+ backup = dup
21
+ reopen other
22
+ yield self
23
+ reopen backup
24
+ end
25
+
26
+ def reread length = nil, buffer: nil
27
+ tap(&:rewind).read length, buffer
28
+ end
29
+
30
+ def squelch &block
31
+ self.class.void.then { |void| redirect(void, &block) }
32
+ end
33
+ end
34
+ end
35
+ end
@@ -13,8 +13,8 @@ module Refinements
13
13
  end
14
14
 
15
15
  refine Pathname do
16
- def name
17
- basename extname
16
+ def change_dir &block
17
+ block_given? ? Dir.chdir(self, &block) : (Dir.chdir self and self)
18
18
  end
19
19
 
20
20
  def copy to
@@ -39,6 +39,28 @@ module Refinements
39
39
  self.class.new to_s.gsub(pattern, replacement)
40
40
  end
41
41
 
42
+ def make_ancestors
43
+ dirname.mkpath
44
+ self
45
+ end
46
+
47
+ def make_dir
48
+ exist? ? self : mkdir and self
49
+ end
50
+
51
+ def make_path
52
+ mkpath
53
+ self
54
+ end
55
+
56
+ def mkdir
57
+ exist? ? self : super and self
58
+ end
59
+
60
+ def name
61
+ basename extname
62
+ end
63
+
42
64
  def relative_parent root_dir
43
65
  relative_path_from(root_dir).parent
44
66
  end
@@ -49,8 +71,12 @@ module Refinements
49
71
  relative_parent root_dir
50
72
  end
51
73
 
52
- def make_ancestors
53
- dirname.mkpath
74
+ def remove_dir
75
+ exist? ? (rmdir and self) : self
76
+ end
77
+
78
+ def remove_tree
79
+ rmtree if exist?
54
80
  self
55
81
  end
56
82
 
@@ -12,6 +12,24 @@ module Refinements
12
12
  end
13
13
 
14
14
  refine String do
15
+ def blank?
16
+ match?(/\A\s*\z/)
17
+ end
18
+
19
+ def camelcase
20
+ return up unless match? DELIMITERS
21
+
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 }
25
+ end
26
+
27
+ def down
28
+ return self if empty?
29
+
30
+ first.downcase + self[1, size]
31
+ end
32
+
15
33
  def first number = 0
16
34
  return self if empty?
17
35
 
@@ -23,6 +41,12 @@ module Refinements
23
41
  self[..(max - 1)]
24
42
  end
25
43
 
44
+ def indent multiplier = 1, padding: " "
45
+ return self if multiplier.negative?
46
+
47
+ padding * multiplier + self
48
+ end
49
+
26
50
  def last number = 0
27
51
  return self if empty?
28
52
 
@@ -34,30 +58,6 @@ module Refinements
34
58
  self[(min + 1)..]
35
59
  end
36
60
 
37
- def blank?
38
- match?(/\A\s*\z/)
39
- end
40
-
41
- def up
42
- return self if empty?
43
-
44
- first.upcase + self[1, size]
45
- end
46
-
47
- def down
48
- return self if empty?
49
-
50
- first.downcase + self[1, size]
51
- end
52
-
53
- def camelcase
54
- return up unless match? DELIMITERS
55
-
56
- split(%r(\s*-\s*|\s*/\s*|\s*:+\s*)).then { |parts| combine parts, :up, "::" }
57
- .then { |text| text.split(/\s*_\s*|\s+/) }
58
- .then { |parts| combine parts, :up }
59
- end
60
-
61
61
  def snakecase
62
62
  return downcase unless match? DELIMITERS
63
63
 
@@ -78,6 +78,12 @@ module Refinements
78
78
  %w[true yes on t y 1].include? downcase.strip
79
79
  end
80
80
 
81
+ def up
82
+ return self if empty?
83
+
84
+ first.upcase + self[1, size]
85
+ end
86
+
81
87
  private
82
88
 
83
89
  # :reek:DuplicateMethodCall
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.9.0
4
+ version: 7.14.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-09-19 00:00:00.000000000 Z
31
+ date: 2020-11-14 00:00:00.000000000 Z
32
32
  dependencies:
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: bundler-audit
@@ -36,42 +36,28 @@ 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
- name: gemsmith
48
+ name: bundler-leak
49
49
  requirement: !ruby/object:Gem::Requirement
50
50
  requirements:
51
51
  - - "~>"
52
52
  - !ruby/object:Gem::Version
53
- version: '14.2'
53
+ version: '0.2'
54
54
  type: :development
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
57
  requirements:
58
58
  - - "~>"
59
59
  - !ruby/object:Gem::Version
60
- version: '14.2'
61
- - !ruby/object:Gem::Dependency
62
- name: git-lint
63
- requirement: !ruby/object:Gem::Requirement
64
- requirements:
65
- - - "~>"
66
- - !ruby/object:Gem::Version
67
- version: '1.0'
68
- type: :development
69
- prerelease: false
70
- version_requirements: !ruby/object:Gem::Requirement
71
- requirements:
72
- - - "~>"
73
- - !ruby/object:Gem::Version
74
- version: '1.0'
60
+ version: '0.2'
75
61
  - !ruby/object:Gem::Dependency
76
62
  name: guard-rspec
77
63
  requirement: !ruby/object:Gem::Requirement
@@ -148,42 +134,42 @@ dependencies:
148
134
  requirements:
149
135
  - - "~>"
150
136
  - !ruby/object:Gem::Version
151
- version: '3.9'
137
+ version: '3.10'
152
138
  type: :development
153
139
  prerelease: false
154
140
  version_requirements: !ruby/object:Gem::Requirement
155
141
  requirements:
156
142
  - - "~>"
157
143
  - !ruby/object:Gem::Version
158
- version: '3.9'
144
+ version: '3.10'
159
145
  - !ruby/object:Gem::Dependency
160
146
  name: rubocop
161
147
  requirement: !ruby/object:Gem::Requirement
162
148
  requirements:
163
149
  - - "~>"
164
150
  - !ruby/object:Gem::Version
165
- version: '0.89'
151
+ version: '1.3'
166
152
  type: :development
167
153
  prerelease: false
168
154
  version_requirements: !ruby/object:Gem::Requirement
169
155
  requirements:
170
156
  - - "~>"
171
157
  - !ruby/object:Gem::Version
172
- version: '0.89'
158
+ version: '1.3'
173
159
  - !ruby/object:Gem::Dependency
174
160
  name: rubocop-performance
175
161
  requirement: !ruby/object:Gem::Requirement
176
162
  requirements:
177
163
  - - "~>"
178
164
  - !ruby/object:Gem::Version
179
- version: '1.5'
165
+ version: '1.8'
180
166
  type: :development
181
167
  prerelease: false
182
168
  version_requirements: !ruby/object:Gem::Requirement
183
169
  requirements:
184
170
  - - "~>"
185
171
  - !ruby/object:Gem::Version
186
- version: '1.5'
172
+ version: '1.8'
187
173
  - !ruby/object:Gem::Dependency
188
174
  name: rubocop-rake
189
175
  requirement: !ruby/object:Gem::Requirement
@@ -204,14 +190,14 @@ dependencies:
204
190
  requirements:
205
191
  - - "~>"
206
192
  - !ruby/object:Gem::Version
207
- version: '1.39'
193
+ version: '2.0'
208
194
  type: :development
209
195
  prerelease: false
210
196
  version_requirements: !ruby/object:Gem::Requirement
211
197
  requirements:
212
198
  - - "~>"
213
199
  - !ruby/object:Gem::Version
214
- version: '1.39'
200
+ version: '2.0'
215
201
  - !ruby/object:Gem::Dependency
216
202
  name: simplecov
217
203
  requirement: !ruby/object:Gem::Requirement
@@ -244,6 +230,7 @@ files:
244
230
  - lib/refinements/files.rb
245
231
  - lib/refinements/hashes.rb
246
232
  - lib/refinements/identity.rb
233
+ - lib/refinements/ios.rb
247
234
  - lib/refinements/pathnames.rb
248
235
  - lib/refinements/string_ios.rb
249
236
  - lib/refinements/strings.rb
metadata.gz.sig CHANGED
Binary file