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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dfa8c1ad4940f61e609e0b70618493a050979540beb9e3388828d9c8741f9103
4
- data.tar.gz: a4851a664e888577d68a01fc9830d9d8c812ff5758edce994eacd0f1440887f4
3
+ metadata.gz: f3a8a85bd0554c198bd29acae4a9f4d5126fd34d9907dd3b9b8b65c03cc32f86
4
+ data.tar.gz: 580151bb2f1a764ad993d25ae0e615095c37b4d61a6f454b4d6e9be300e6ed39
5
5
  SHA512:
6
- metadata.gz: dd750b905857c86db3cdd8c054c50a7900e2ef194fdd51df69bd35267f0f947bbb93dca3df9bb7596758b15a5312203cb02875ff99c90eca03aab7d63c064e79
7
- data.tar.gz: 6c9c6198b3ef913c4cfebcae52cc85573a499a29b4d21eb2826e22f13dfd58f20fa96333faa92a3ff2d7e88ad38df97247d1836b7b554eb859e59dcd17f03bd2
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
- ## [Unreleased]
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
- ## [0.4.0]
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.4.0...HEAD
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.with_key { |k, v| "User #{k}: #{v[:name]}" }
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.4 development environment";
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
- (ruby_3_4.override {
23
+ (ruby_3_2.override {
24
24
  jemallocSupport = true;
25
25
  docSupport = false;
26
26
  })
@@ -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
- # Transforms hash values while allowing access to keys via the chainable with_key method
261
+ # Returns a new hash with all values transformed by the block
261
262
  #
262
- # This method either performs a standard transform_values operation if a block is given,
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
- # @yield [value] Block to transform each value (standard behavior)
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, Enumerator] Result hash or Enumerator with with_key method
272
+ # @return [Hash] A new hash with transformed values
273
+ # @return [Enumerator] If no block is given
271
274
  #
272
- # @example Standard transform_values
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 Using with_key to access keys during transformation
277
- # {a: 1, b: 2}.transform_values.with_key { |k, v| "#{k}_#{v}" }
278
- # # => {a: "a_1", b: "b_2"}
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 transform_values_enumerator if block.nil?
283
+ def transform_values(with_key: false, &block)
284
+ return to_enum(:transform_values, with_key:) if block.nil?
282
285
 
283
- og_transform_values(&block)
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 hash values in place while allowing access to keys via the chainable with_key method
296
+ # Transforms all values in the hash in place
297
+ #
298
+ # Enhances Ruby's standard transform_values! with key access capability.
288
299
  #
289
- # This method either performs a standard transform_values! operation if a block is given,
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 to transform each value (standard behavior)
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, Enumerator]
298
- # Original hash with transformed values or Enumerator with with_key method
307
+ # @return [self] The transformed hash
308
+ # @return [Enumerator] If no block is given
299
309
  #
300
- # @example Standard transform_values!
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 Using with_key to access keys during in-place transformation
316
+ # @example With key access
306
317
  # hash = {a: 1, b: 2}
307
- # hash.transform_values!.with_key { |k, v| "#{k}_#{v}" }
308
- # # => {a: "a_1", b: "b_2"}
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 transform_values_bang_enumerator if block.nil?
322
+ def transform_values!(with_key: false, &block)
323
+ return to_enum(:transform_values!, with_key:) if block.nil?
312
324
 
313
- og_transform_values!(&block)
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
@@ -7,5 +7,5 @@
7
7
  #
8
8
  module Everythingrb
9
9
  # Current version of the everythingrb gem
10
- VERSION = "0.4.0"
10
+ VERSION = "0.6.0"
11
11
  end
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.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-12 00:00:00.000000000 Z
11
+ date: 2025-04-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ostruct