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