everythingrb 0.4.0 → 0.6.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
- data/CHANGELOG.md +49 -3
- data/README.md +3 -2
- data/flake.nix +2 -2
- data/lib/everythingrb/hash.rb +204 -63
- data/lib/everythingrb/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f3a8a85bd0554c198bd29acae4a9f4d5126fd34d9907dd3b9b8b65c03cc32f86
|
4
|
+
data.tar.gz: 580151bb2f1a764ad993d25ae0e615095c37b4d61a6f454b4d6e9be300e6ed39
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a10e0a0980a4a061d8103f0ec99523094320b432bf5c15e367313d0be06bdadb22ee0fcaae037fdbb233501aa48081a84502c03c74a7e786e573f1679fb81549
|
7
|
+
data.tar.gz: e6a2368422b235a1d5859f0afb3dbc908d777d5098296cf64f10cd212f2e6d23f7dc6a5d6cb740e0a71da833536bcf7351934895ae73294a62026ac052bb3ee9
|
data/CHANGELOG.md
CHANGED
@@ -15,15 +15,60 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
15
15
|
### Removed
|
16
16
|
-->
|
17
17
|
|
18
|
-
## [
|
18
|
+
## [0.6.0] - 12025-04-26
|
19
|
+
|
20
|
+
### BREAKING CHANGES:
|
21
|
+
|
22
|
+
- **Replaced method-based `with_key` approach with direct parameter**:
|
23
|
+
The chainable `.with_key` method approach has been replaced with a more straightforward parameter-based approach.
|
24
|
+
|
25
|
+
**Before:**
|
26
|
+
```ruby
|
27
|
+
hash.transform_values.with_key { |value, key| "#{key}:#{value}" }
|
28
|
+
hash.transform_values!.with_key { |value, key| "#{key}:#{value}" }
|
29
|
+
```
|
30
|
+
|
31
|
+
**After:**
|
32
|
+
```ruby
|
33
|
+
hash.transform_values(with_key: true) { |value, key| "#{key}:#{value}" }
|
34
|
+
hash.transform_values!(with_key: true) { |value, key| "#{key}:#{value}" }
|
35
|
+
```
|
36
|
+
|
37
|
+
### Added:
|
38
|
+
|
39
|
+
- Added ActiveSupport integration for deep transforms with key access:
|
40
|
+
- `Hash#deep_transform_values(with_key: true)`
|
41
|
+
- `Hash#deep_transform_values!(with_key: true)`
|
42
|
+
|
43
|
+
## [0.5.0] - 12025-04-17
|
44
|
+
|
45
|
+
**BREAKING:**
|
46
|
+
|
47
|
+
The parameter order in `Hash#transform_values.with_key` has been changed to yield `|value, key|` instead of `|key, value|` to maintain consistency with Ruby's standard enumeration methods like `each_with_index`.
|
48
|
+
|
49
|
+
**Before:**
|
50
|
+
```ruby
|
51
|
+
hash.transform_values.with_key { |key, value| "#{key}: #{value}" }
|
52
|
+
```
|
53
|
+
|
54
|
+
**After:**
|
55
|
+
```ruby
|
56
|
+
hash.transform_values.with_key { |value, key| "#{key}: #{value}" }
|
57
|
+
```
|
58
|
+
|
59
|
+
This change aligns our method signatures with Ruby's conventions and matches our other methods like `join_map(with_index: true)` which yields `|value, index|`.
|
19
60
|
|
20
61
|
### Added
|
21
62
|
|
63
|
+
- Added `Hash#transform` and `Hash#transform!` for transforming a hash's keys and values at the same time.
|
64
|
+
|
22
65
|
### Changed
|
66
|
+
- Changed parameter order in `Hash#transform_values.with_key` to yield `|value, key|` instead of `|key, value|` for consistency with Ruby conventions.
|
23
67
|
|
24
68
|
### Removed
|
25
69
|
|
26
|
-
|
70
|
+
|
71
|
+
## [0.4.0] - 12025-04-11
|
27
72
|
|
28
73
|
### Added
|
29
74
|
|
@@ -170,7 +215,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
170
215
|
|
171
216
|
- Added alias `each` to `each_pair` in OpenStruct for better enumerable compatibility
|
172
217
|
|
173
|
-
[unreleased]: https://github.com/itsthedevman/everythingrb/compare/v0.
|
218
|
+
[unreleased]: https://github.com/itsthedevman/everythingrb/compare/v0.5.0...HEAD
|
219
|
+
[0.5.0]: https://github.com/itsthedevman/everythingrb/compare/v0.4.0...v0.5.0
|
174
220
|
[0.4.0]: https://github.com/itsthedevman/everythingrb/compare/v0.3.1...v0.4.0
|
175
221
|
[0.3.1]: https://github.com/itsthedevman/everythingrb/compare/v0.3.0...v0.3.1
|
176
222
|
[0.3.0]: https://github.com/itsthedevman/everythingrb/compare/v0.2.5...v0.3.0
|
data/README.md
CHANGED
@@ -7,8 +7,9 @@
|
|
7
7
|
Super handy extensions to Ruby core classes that make your code more expressive, readable, and fun to write.
|
8
8
|
|
9
9
|
```ruby
|
10
|
-
# Instead of this:
|
11
10
|
users = [{ name: "Alice", role: "admin" }, { name: "Bob", role: "user" }]
|
11
|
+
|
12
|
+
# Instead of this:
|
12
13
|
admin_names = users.select { |u| u[:role] == "admin" }.map { |u| u[:name] }.join(", ")
|
13
14
|
|
14
15
|
# Write this:
|
@@ -141,7 +142,7 @@ stats[:server][:region][:us_east][:errors] << "Connection timeout"
|
|
141
142
|
# No need to initialize each level first!
|
142
143
|
|
143
144
|
# Transform values with access to keys
|
144
|
-
users.transform_values
|
145
|
+
users.transform_values(with_key: true) { |v, k| "User #{k}: #{v[:name]}" }
|
145
146
|
|
146
147
|
# Find values based on conditions
|
147
148
|
users.values_where { |k, v| v[:role] == "admin" }
|
data/flake.nix
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
{
|
2
|
-
description = "Ruby 3.
|
2
|
+
description = "Ruby 3.2 development environment";
|
3
3
|
|
4
4
|
inputs = {
|
5
5
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
@@ -20,7 +20,7 @@
|
|
20
20
|
{
|
21
21
|
devShells.default = pkgs.mkShell {
|
22
22
|
buildInputs = with pkgs; [
|
23
|
-
(
|
23
|
+
(ruby_3_2.override {
|
24
24
|
jemallocSupport = true;
|
25
25
|
docSupport = false;
|
26
26
|
})
|
data/lib/everythingrb/hash.rb
CHANGED
@@ -8,6 +8,7 @@
|
|
8
8
|
# - #join_map: Combine filter_map and join operations
|
9
9
|
# - #deep_freeze: Recursively freeze hash and contents
|
10
10
|
# - #transform_values.with_key: Transform values with access to keys
|
11
|
+
# - #transform, #transform!: Transform keys and values
|
11
12
|
# - #value_where, #values_where: Find values based on conditions
|
12
13
|
# - #rename_key, #rename_keys: Rename hash keys while preserving order
|
13
14
|
# - ::new_nested_hash: Create automatically nesting hashes
|
@@ -257,60 +258,236 @@ class Hash
|
|
257
258
|
alias_method :og_transform_values!, :transform_values!
|
258
259
|
|
259
260
|
#
|
260
|
-
#
|
261
|
+
# Returns a new hash with all values transformed by the block
|
261
262
|
#
|
262
|
-
#
|
263
|
-
# or returns an enumerator with a with_key method that passes both the key and value
|
264
|
-
# to the block.
|
263
|
+
# Enhances Ruby's standard transform_values with key access capability.
|
265
264
|
#
|
266
|
-
# @
|
265
|
+
# @param with_key [Boolean] Whether to yield both value and key to the block
|
266
|
+
#
|
267
|
+
# @yield [value, key] Block that transforms each value
|
267
268
|
# @yieldparam value [Object] The value to transform
|
269
|
+
# @yieldparam key [Object] The corresponding key (only if with_key: true)
|
268
270
|
# @yieldreturn [Object] The transformed value
|
269
271
|
#
|
270
|
-
# @return [Hash
|
272
|
+
# @return [Hash] A new hash with transformed values
|
273
|
+
# @return [Enumerator] If no block is given
|
271
274
|
#
|
272
|
-
# @example Standard
|
275
|
+
# @example Standard usage
|
273
276
|
# {a: 1, b: 2}.transform_values { |v| v * 2 }
|
274
277
|
# # => {a: 2, b: 4}
|
275
278
|
#
|
276
|
-
# @example
|
277
|
-
# {a: 1, b: 2}.transform_values
|
278
|
-
# # => {a: "
|
279
|
+
# @example With key access
|
280
|
+
# {a: 1, b: 2}.transform_values(with_key: true) { |v, k| "#{k}:#{v}" }
|
281
|
+
# # => {a: "a:1", b: "b:2"}
|
279
282
|
#
|
280
|
-
def transform_values(&block)
|
281
|
-
return
|
283
|
+
def transform_values(with_key: false, &block)
|
284
|
+
return to_enum(:transform_values, with_key:) if block.nil?
|
282
285
|
|
283
|
-
|
286
|
+
if with_key
|
287
|
+
each_pair.with_object({}) do |(key, value), output|
|
288
|
+
output[key] = block.call(value, key)
|
289
|
+
end
|
290
|
+
else
|
291
|
+
og_transform_values(&block)
|
292
|
+
end
|
284
293
|
end
|
285
294
|
|
286
295
|
#
|
287
|
-
# Transforms
|
296
|
+
# Transforms all values in the hash in place
|
297
|
+
#
|
298
|
+
# Enhances Ruby's standard transform_values! with key access capability.
|
288
299
|
#
|
289
|
-
#
|
290
|
-
# or returns an enumerator with a with_key method that passes both the key and value
|
291
|
-
# to the block, updating the hash in place.
|
300
|
+
# @param with_key [Boolean] Whether to yield both value and key to the block
|
292
301
|
#
|
293
|
-
# @yield [value] Block
|
302
|
+
# @yield [value, key] Block that transforms each value
|
294
303
|
# @yieldparam value [Object] The value to transform
|
304
|
+
# @yieldparam key [Object] The corresponding key (only if with_key: true)
|
295
305
|
# @yieldreturn [Object] The transformed value
|
296
306
|
#
|
297
|
-
# @return [self
|
298
|
-
#
|
307
|
+
# @return [self] The transformed hash
|
308
|
+
# @return [Enumerator] If no block is given
|
299
309
|
#
|
300
|
-
# @example Standard
|
310
|
+
# @example Standard usage
|
301
311
|
# hash = {a: 1, b: 2}
|
302
312
|
# hash.transform_values! { |v| v * 2 }
|
303
313
|
# # => {a: 2, b: 4}
|
314
|
+
# # hash is now {a: 2, b: 4}
|
304
315
|
#
|
305
|
-
# @example
|
316
|
+
# @example With key access
|
306
317
|
# hash = {a: 1, b: 2}
|
307
|
-
# hash.transform_values
|
308
|
-
# # => {a: "
|
318
|
+
# hash.transform_values!(with_key: true) { |v, k| "#{k}:#{v}" }
|
319
|
+
# # => {a: "a:1", b: "b:2"}
|
320
|
+
# # hash is now {a: "a:1", b: "b:2"}
|
309
321
|
#
|
310
|
-
def transform_values!(&block)
|
311
|
-
return
|
322
|
+
def transform_values!(with_key: false, &block)
|
323
|
+
return to_enum(:transform_values!, with_key:) if block.nil?
|
312
324
|
|
313
|
-
|
325
|
+
if with_key
|
326
|
+
each_pair do |key, value|
|
327
|
+
self[key] = block.call(value, key)
|
328
|
+
end
|
329
|
+
else
|
330
|
+
og_transform_values!(&block)
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
# ActiveSupport integrations
|
335
|
+
if defined?(ActiveSupport)
|
336
|
+
# Allows calling original method. See below
|
337
|
+
alias_method :og_deep_transform_values, :deep_transform_values
|
338
|
+
|
339
|
+
# Allows calling original method. See below
|
340
|
+
alias_method :og_deep_transform_values!, :deep_transform_values!
|
341
|
+
|
342
|
+
#
|
343
|
+
# Recursively transforms all values in the hash and nested structures
|
344
|
+
#
|
345
|
+
# Walks through the hash and all nested hashes/arrays and yields each non-hash and
|
346
|
+
# non-array value to the block, replacing it with the block's return value.
|
347
|
+
#
|
348
|
+
# @param with_key [Boolean] Whether to yield both value and key to the block
|
349
|
+
#
|
350
|
+
# @yield [value, key] Block that transforms each value
|
351
|
+
# @yieldparam value [Object] The value to transform
|
352
|
+
# @yieldparam key [Object] The corresponding key (only if with_key: true)
|
353
|
+
# @yieldreturn [Object] The transformed value
|
354
|
+
#
|
355
|
+
# @return [Hash] A new hash with all values recursively transformed
|
356
|
+
# @return [Enumerator] If no block is given
|
357
|
+
#
|
358
|
+
# @example Basic usage
|
359
|
+
# hash = {a: 1, b: {c: 2, d: [3, 4]}}
|
360
|
+
# hash.deep_transform_values { |v| v * 2 }
|
361
|
+
# # => {a: 2, b: {c: 4, d: [6, 8]}}
|
362
|
+
#
|
363
|
+
# @example With key access
|
364
|
+
# hash = {a: 1, b: {c: 2}}
|
365
|
+
# hash.deep_transform_values(with_key: true) { |v, k| "#{k}:#{v}" }
|
366
|
+
# # => {a: "a:1", b: {c: "c:2"}}
|
367
|
+
#
|
368
|
+
def deep_transform_values(with_key: false, &block)
|
369
|
+
return to_enum(:deep_transform_values, with_key:) if block.nil?
|
370
|
+
|
371
|
+
if with_key
|
372
|
+
_deep_transform_values_with_key(self, nil, &block)
|
373
|
+
else
|
374
|
+
og_deep_transform_values(&block)
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
378
|
+
#
|
379
|
+
# Recursively transforms all values in the hash and nested structures in place
|
380
|
+
#
|
381
|
+
# Same as #deep_transform_values but modifies the hash in place.
|
382
|
+
#
|
383
|
+
# @param with_key [Boolean] Whether to yield both value and key to the block
|
384
|
+
#
|
385
|
+
# @yield [value, key] Block that transforms each value
|
386
|
+
# @yieldparam value [Object] The value to transform
|
387
|
+
# @yieldparam key [Object] The corresponding key (only if with_key: true)
|
388
|
+
# @yieldreturn [Object] The transformed value
|
389
|
+
#
|
390
|
+
# @return [self] The transformed hash
|
391
|
+
# @return [Enumerator] If no block is given
|
392
|
+
#
|
393
|
+
# @example Basic usage
|
394
|
+
# hash = {a: 1, b: {c: 2, d: [3, 4]}}
|
395
|
+
# hash.deep_transform_values! { |v| v * 2 }
|
396
|
+
# # => {a: 2, b: {c: 4, d: [6, 8]}}
|
397
|
+
# # hash is now {a: 2, b: {c: 4, d: [6, 8]}}
|
398
|
+
#
|
399
|
+
# @example With key access
|
400
|
+
# hash = {a: 1, b: {c: 2}}
|
401
|
+
# hash.deep_transform_values!(with_key: true) { |v, k| "#{k}:#{v}" }
|
402
|
+
# # => {a: "a:1", b: {c: "c:2"}}
|
403
|
+
# # hash is now {a: "a:1", b: {c: "c:2"}}
|
404
|
+
#
|
405
|
+
def deep_transform_values!(with_key: false, &block)
|
406
|
+
return to_enum(:deep_transform_values!, with_key:) if block.nil?
|
407
|
+
|
408
|
+
if with_key
|
409
|
+
_deep_transform_values_with_key!(self, nil, &block)
|
410
|
+
else
|
411
|
+
og_deep_transform_values!(&block)
|
412
|
+
end
|
413
|
+
end
|
414
|
+
|
415
|
+
private
|
416
|
+
|
417
|
+
# https://github.com/rails/rails/blob/main/activesupport/lib/active_support/core_ext/hash/deep_transform_values.rb#L25
|
418
|
+
def _deep_transform_values_with_key(object, key, &block)
|
419
|
+
case object
|
420
|
+
when Hash
|
421
|
+
object.transform_values(with_key: true) do |value, key|
|
422
|
+
_deep_transform_values_with_key(value, key, &block)
|
423
|
+
end
|
424
|
+
when Array
|
425
|
+
object.map do |value|
|
426
|
+
_deep_transform_values_with_key(value, nil, &block)
|
427
|
+
end
|
428
|
+
else
|
429
|
+
block.call(object, key)
|
430
|
+
end
|
431
|
+
end
|
432
|
+
|
433
|
+
# https://github.com/rails/rails/blob/main/activesupport/lib/active_support/core_ext/hash/deep_transform_values.rb#L36
|
434
|
+
def _deep_transform_values_with_key!(object, key, &block)
|
435
|
+
case object
|
436
|
+
when Hash
|
437
|
+
object.transform_values!(with_key: true) do |value, key|
|
438
|
+
_deep_transform_values_with_key!(value, key, &block)
|
439
|
+
end
|
440
|
+
when Array
|
441
|
+
object.map! do |value|
|
442
|
+
_deep_transform_values_with_key!(value, nil, &block)
|
443
|
+
end
|
444
|
+
else
|
445
|
+
block.call(object, key)
|
446
|
+
end
|
447
|
+
end
|
448
|
+
end
|
449
|
+
|
450
|
+
#
|
451
|
+
# Transforms keys and values to create a new hash
|
452
|
+
#
|
453
|
+
# @yield [key, value] Block that returns a new key-value pair
|
454
|
+
# @yieldparam key [Object] The original key
|
455
|
+
# @yieldparam value [Object] The original value
|
456
|
+
# @yieldreturn [Array] Two-element array containing the new key and value
|
457
|
+
#
|
458
|
+
# @return [Hash] A new hash with transformed keys and values
|
459
|
+
# @return [Enumerator] If no block is given
|
460
|
+
#
|
461
|
+
# @example Transform both keys and values
|
462
|
+
# {a: 1, b: 2}.transform { |k, v| ["#{k}_key", v * 2] }
|
463
|
+
# # => {a_key: 2, b_key: 4}
|
464
|
+
#
|
465
|
+
def transform(&block)
|
466
|
+
return to_enum(:transform) if block.nil?
|
467
|
+
|
468
|
+
to_h(&block)
|
469
|
+
end
|
470
|
+
|
471
|
+
#
|
472
|
+
# Transforms keys and values in place
|
473
|
+
#
|
474
|
+
# @yield [key, value] Block that returns a new key-value pair
|
475
|
+
# @yieldparam key [Object] The original key
|
476
|
+
# @yieldparam value [Object] The original value
|
477
|
+
# @yieldreturn [Array] Two-element array containing the new key and value
|
478
|
+
#
|
479
|
+
# @return [self] The transformed hash
|
480
|
+
# @return [Enumerator] If no block is given
|
481
|
+
#
|
482
|
+
# @example Transform both keys and values in place
|
483
|
+
# hash = {a: 1, b: 2}
|
484
|
+
# hash.transform! { |k, v| ["#{k}_key", v * 2] }
|
485
|
+
# # => {a_key: 2, b_key: 4}
|
486
|
+
#
|
487
|
+
def transform!(&block)
|
488
|
+
return to_enum(:transform!) if block.nil?
|
489
|
+
|
490
|
+
replace(transform(&block))
|
314
491
|
end
|
315
492
|
|
316
493
|
#
|
@@ -484,40 +661,4 @@ class Hash
|
|
484
661
|
self[new_key] = delete(old_key)
|
485
662
|
self
|
486
663
|
end
|
487
|
-
|
488
|
-
private
|
489
|
-
|
490
|
-
def transform_values_enumerator
|
491
|
-
original_hash = self
|
492
|
-
enum = to_enum(:transform_values)
|
493
|
-
|
494
|
-
# Add the with_key method directly to the enum
|
495
|
-
enum.define_singleton_method(:with_key) do |&block|
|
496
|
-
raise ArgumentError, "Missing block for Hash#transform_values.with_key" if block.nil?
|
497
|
-
|
498
|
-
original_hash.each_pair.with_object({}) do |(key, value), output|
|
499
|
-
output[key] = block.call(key, value)
|
500
|
-
end
|
501
|
-
end
|
502
|
-
|
503
|
-
enum
|
504
|
-
end
|
505
|
-
|
506
|
-
def transform_values_bang_enumerator
|
507
|
-
original_hash = self
|
508
|
-
enum = to_enum(:transform_values!)
|
509
|
-
|
510
|
-
# Add the with_key method directly to the enum
|
511
|
-
enum.define_singleton_method(:with_key) do |&block|
|
512
|
-
raise ArgumentError, "Missing block for Hash#transform_values!.with_key" if block.nil?
|
513
|
-
|
514
|
-
original_hash.each_pair do |key, value|
|
515
|
-
original_hash[key] = block.call(key, value)
|
516
|
-
end
|
517
|
-
|
518
|
-
original_hash
|
519
|
-
end
|
520
|
-
|
521
|
-
enum
|
522
|
-
end
|
523
664
|
end
|
data/lib/everythingrb/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: everythingrb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bryan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-04-
|
11
|
+
date: 2025-04-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ostruct
|