everythingrb 0.3.1 → 0.5.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: 747441fc1a0c8be071a4465edb190dead79eea7195b66b262976e8ae91b6bc0f
4
- data.tar.gz: 491c3bc6c22bc02495425fecfb51166c8982d86ad0eede1b10980e2bf040b705
3
+ metadata.gz: 320458b0c0e09c8556129b456eb191ff588a6b2277b5da46a5273dc36c4f3a50
4
+ data.tar.gz: 824f8c91fbe4749022a8a5f2caf6d6f76714a6d7faf747a4f25818342d5d5b39
5
5
  SHA512:
6
- metadata.gz: f6605c462aeeb634fe3342a3befb424fe3a67f31059f486d4c835a3670192962a44f6237f51947629cbe1a27d7a21579c03a48f9c98e22f155821cdb62f1e8c1
7
- data.tar.gz: e6d2ce8fca0b90b513c686dfc44f8010cfb2aca9cc3be84cdbd08c6fccbbac49727ffbe42805f5a0789496df7b3f68ace624b7c201b30f5ee5305be16af485fa
6
+ metadata.gz: ac7ed45151941a1e124372ebfb1394fb8176f4703bc903fa634d3672a251c8a4e497f8555bc1433848512d7e8edb04926c8a043420d3337041c7fc00e9e7eebd
7
+ data.tar.gz: b0d711b08f5ec75aa07ab009587784a926f2e5832a35037da89a96fa5d800a29e4e4b1c3beb81ba6b86b3d5821252aeda2ab2f124234f859af477cbeb186a8cb
data/CHANGELOG.md CHANGED
@@ -23,6 +23,58 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
23
23
 
24
24
  ### Removed
25
25
 
26
+ ## [0.5.0] - 12025-04-17
27
+
28
+ **BREAKING:**
29
+
30
+ 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`.
31
+
32
+ **Before:**
33
+ ```ruby
34
+ hash.transform_values.with_key { |key, value| "#{key}: #{value}" }
35
+ ```
36
+
37
+ **After:**
38
+ ```ruby
39
+ hash.transform_values.with_key { |value, key| "#{key}: #{value}" }
40
+ ```
41
+
42
+ 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|`.
43
+
44
+ ### Added
45
+
46
+ - Added `Hash#transform` and `Hash#transform!` for transforming a hash's keys and values at the same time.
47
+
48
+ ### Changed
49
+ - Changed parameter order in `Hash#transform_values.with_key` to yield `|value, key|` instead of `|key, value|` for consistency with Ruby conventions.
50
+
51
+ ### Removed
52
+
53
+
54
+ ## [0.4.0] - 12025-04-11
55
+
56
+ ### Added
57
+
58
+ - Added new `Hash` methods for renaming keys:
59
+ - `#rename_key` - Renames a key in the hash while preserving the original order of elements
60
+ - `#rename_key!` - Same as `#rename_key` but modifies the hash in place
61
+ - `#rename_keys` - Renames multiple keys in the hash while preserving the original order of elements
62
+ - `#rename_keys!` - Same as `#rename_keys` but modifies the hash in place
63
+ - `#rename_key_unordered` - Renames a key without preserving element order (faster operation)
64
+ - `#rename_key_unordered!` - Same as `#rename_key_unordered` but modifies the hash in place
65
+ - Added `to_deep_h` to core Ruby classes for consistent deep hash conversion:
66
+ - `Struct#to_deep_h` - Recursively converts Struct objects and all nested values to hashes
67
+ - `OpenStruct#to_deep_h` - Recursively converts OpenStruct objects and all nested values to hashes
68
+ - `Data#to_deep_h` - Recursively converts Data objects and all nested values to hashes
69
+ - Added `depth` parameter to `Hash.new_nested_hash` to control nesting behaviors
70
+
71
+ ### Changed
72
+
73
+ - Reorganized internal file structure for better modularity with full backward compatibility
74
+ - Updated documentation headers to each module file explaining available extensions
75
+
76
+ ### Removed
77
+
26
78
  ## [0.3.1] - 12025-04-09
27
79
 
28
80
  ### Added
@@ -74,7 +126,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
74
126
 
75
127
  - Added `Symbol#with_quotes` and `Symbol#in_quotes`
76
128
 
77
-
78
129
  ## [0.2.2] - 12025-03-03
79
130
 
80
131
  ### Added
@@ -94,7 +145,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
94
145
 
95
146
  - Removed `Data` definition check for `to_istruct`
96
147
 
97
-
98
148
  ## [0.2.0] - 12025-02-17
99
149
 
100
150
  ### Added
@@ -119,7 +169,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
119
169
 
120
170
  - Separated out tests that require `ActiveSupport` into their own test process. Files that end with `_active_support` will be tested separately with ActiveSupport loaded
121
171
 
122
-
123
172
  ## [0.1.1] - 12025-02-07
124
173
 
125
174
  ### Added
@@ -149,7 +198,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
149
198
 
150
199
  - Added alias `each` to `each_pair` in OpenStruct for better enumerable compatibility
151
200
 
152
- [unreleased]: https://github.com/itsthedevman/everythingrb/compare/v0.3.1...HEAD
201
+ [unreleased]: https://github.com/itsthedevman/everythingrb/compare/v0.5.0...HEAD
202
+ [0.5.0]: https://github.com/itsthedevman/everythingrb/compare/v0.4.0...v0.5.0
203
+ [0.4.0]: https://github.com/itsthedevman/everythingrb/compare/v0.3.1...v0.4.0
153
204
  [0.3.1]: https://github.com/itsthedevman/everythingrb/compare/v0.3.0...v0.3.1
154
205
  [0.3.0]: https://github.com/itsthedevman/everythingrb/compare/v0.2.5...v0.3.0
155
206
  [0.2.5]: https://github.com/itsthedevman/everythingrb/compare/v0.2.4...v0.2.5
data/README.md CHANGED
@@ -25,6 +25,53 @@ gem "everythingrb"
25
25
  gem install everythingrb
26
26
  ```
27
27
 
28
+ ## Usage
29
+
30
+ There are two ways to use EverythingRB:
31
+
32
+ ### Load Everything (Default)
33
+
34
+ The simplest approach - just require and go:
35
+
36
+ ```ruby
37
+ require "everythingrb"
38
+
39
+ # Now you have access to all extensions!
40
+ users = [{name: "Alice"}, {name: "Bob"}]
41
+ users.key_map(:name).join(", ") # => "Alice, Bob"
42
+
43
+ config = {server: {port: 443}}.to_ostruct
44
+ config.server.port # => 443
45
+ ```
46
+
47
+ ### Cherry-Pick Extensions
48
+
49
+ If you only need specific extensions, you can load just what you want:
50
+
51
+ ```ruby
52
+ require "everythingrb/prelude" # Required base module
53
+ require "everythingrb/array" # Just Array extensions
54
+ require "everythingrb/string" # Just String extensions
55
+
56
+ # Now you have access to only the extensions you loaded
57
+ ["a", "b"].join_map(" | ") { |s| s.upcase } # => "A | B"
58
+ '{"name": "Alice"}'.to_ostruct.name # => "Alice"
59
+
60
+ # But Hash extensions aren't loaded yet
61
+ {}.to_ostruct # => NoMethodError
62
+ ```
63
+
64
+ Available modules:
65
+ - `array`: Array extensions (join_map, key_map, etc.)
66
+ - `data`: Data extensions (to_deep_h)
67
+ - `enumerable`: Enumerable extensions (join_map, group_by_key)
68
+ - `hash`: Hash extensions (to_ostruct, deep_freeze, etc.)
69
+ - `module`: Extensions like attr_predicate
70
+ - `ostruct`: OpenStruct extensions (map, join_map, etc.)
71
+ - `string`: String extensions (to_h, to_ostruct, etc.)
72
+ - `struct`: Struct extensions (to_deep_h)
73
+ - `symbol`: Symbol extensions (with_quotes)
74
+
28
75
  ## What's Included
29
76
 
30
77
  EverythingRB extends Ruby's core classes with intuitive methods that simplify common patterns.
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "array"
4
+ require_relative "data"
5
+ require_relative "enumerable"
6
+ require_relative "hash"
7
+ require_relative "module"
8
+ require_relative "ostruct"
9
+ require_relative "string"
10
+ require_relative "struct"
11
+ require_relative "symbol"
@@ -3,18 +3,17 @@
3
3
  #
4
4
  # Extensions to Ruby's core Array class
5
5
  #
6
- # This module adds convenient mapping, joining, and freezing functionality
7
- # to all Arrays in your application.
6
+ # Provides:
7
+ # - #join_map: Combine filter_map and join operations in one step
8
+ # - #key_map, #dig_map: Extract values from arrays of hashes
9
+ # - #deep_freeze: Recursively freeze array and contents
10
+ # - #compact_prefix, #compact_suffix, #trim_nils: Clean up array boundaries
11
+ # - ActiveSupport integrations: #trim_blanks and more when ActiveSupport is loaded
8
12
  #
9
- # @example Using the extensions
10
- # numbers = [1, 2, nil, 3]
11
- #
12
- # # Filter out nils and format odd numbers
13
- # numbers.join_map(", ") { |n| "odd: #{n}" if n&.odd? }
14
- # # => "odd: 1, odd: 3"
15
- #
16
- # users = [{name: "Alice", role: "admin"}, {name: "Bob", role: "user"}]
17
- # users.key_map(:name) # => ["Alice", "Bob"]
13
+ # @example
14
+ # require "everythingrb/array"
15
+ # ["foo", nil, "bar"].join_map(", ") { |s| s&.upcase } # => "FOO, BAR"
16
+ # [{name: "Alice"}, {name: "Bob"}].key_map(:name) # => ["Alice", "Bob"]
18
17
  #
19
18
  class Array
20
19
  #
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Extensions to Ruby's core Data class
5
+ #
6
+ # Provides:
7
+ # - #to_deep_h: Recursively convert to hash with all nested objects
8
+ #
9
+ class Data
10
+ #
11
+ # Recursively converts the Data object and all nested objects to hashes
12
+ #
13
+ # @return [Hash] A deeply converted hash of the Data object
14
+ #
15
+ # @example
16
+ # Person = Data.define(:name, :profile)
17
+ # person = Person.new(name: "Alice", profile: {roles: ["admin"]})
18
+ # person.to_deep_h # => {name: "Alice", profile: {roles: ["admin"]}}
19
+ #
20
+ def to_deep_h
21
+ to_h.to_deep_h
22
+ end
23
+ end
@@ -3,12 +3,14 @@
3
3
  #
4
4
  # Extensions to Ruby's core Enumerable module
5
5
  #
6
- # These additions make working with any enumerable collection more expressive
7
- # by combining common operations into convenient methods.
6
+ # Provides:
7
+ # - #join_map: Combine filter_map and join operations
8
+ # - #group_by_key: Group elements by a given key or nested keys
8
9
  #
9
- # @example Using join_map with a Range
10
- # (1..5).join_map(" | ") { |n| "item-#{n}" if n.even? }
11
- # # => "item-2 | item-4"
10
+ # @example
11
+ # require "everythingrb/enumerable"
12
+ # (1..5).join_map(" | ") { |n| "item-#{n}" if n.even? } # => "item-2 | item-4"
13
+ # users.group_by_key(:role) # Groups users by their role
12
14
  #
13
15
  module Enumerable
14
16
  #
@@ -3,17 +3,20 @@
3
3
  #
4
4
  # Extensions to Ruby's core Hash class
5
5
  #
6
- # These additions make working with hashes more convenient by adding
7
- # conversion methods to different data structures and string formatting helpers.
6
+ # Provides:
7
+ # - #to_struct, #to_ostruct, #to_istruct: Convert hashes to different structures
8
+ # - #join_map: Combine filter_map and join operations
9
+ # - #deep_freeze: Recursively freeze hash and contents
10
+ # - #transform_values.with_key: Transform values with access to keys
11
+ # - #transform, #transform!: Transform keys and values
12
+ # - #value_where, #values_where: Find values based on conditions
13
+ # - #rename_key, #rename_keys: Rename hash keys while preserving order
14
+ # - ::new_nested_hash: Create automatically nesting hashes
8
15
  #
9
- # @example Converting to different structures
10
- # user = { name: "Alice", roles: ["admin"] }
11
- # user.to_struct # => #<struct name="Alice", roles=["admin"]>
12
- # user.to_ostruct # => #<OpenStruct name="Alice", roles=["admin"]>
13
- #
14
- # # Filtering and joining hash entries
15
- # { a: 1, b: nil, c: 3 }.join_map(", ") { |k, v| "#{k}:#{v}" if v }
16
- # # => "a:1, c:3"
16
+ # @example
17
+ # require "everythingrb/hash"
18
+ # config = {server: {port: 443}}.to_ostruct
19
+ # config.server.port # => 443
17
20
  #
18
21
  class Hash
19
22
  #
@@ -33,26 +36,49 @@ class Hash
33
36
  # Creates a new Hash that automatically initializes missing keys with nested hashes
34
37
  #
35
38
  # This method creates a hash where any missing key access will automatically
36
- # create another nested hash with the same behavior, allowing for unlimited
37
- # nesting depth without explicit initialization.
39
+ # create another nested hash with the same behavior. You can control the nesting
40
+ # depth with the depth parameter.
41
+ #
42
+ # @param depth [Integer, nil] The maximum nesting depth for automatic hash creation
43
+ # When nil (default), creates unlimited nesting depth
44
+ # When 0, behaves like a regular hash (returns nil for missing keys)
45
+ # When > 0, automatically creates hashes only up to the specified level
38
46
  #
39
- # @return [Hash] A hash that recursively creates nested hashes for missing keys
47
+ # @return [Hash] A hash that creates nested hashes for missing keys
40
48
  #
41
- # @example Basic usage with two levels
49
+ # @example Unlimited nesting (default behavior)
42
50
  # users = Hash.new_nested_hash
43
51
  # users[:john][:role] = "admin" # No need to initialize users[:john] first
44
52
  # users # => {john: {role: "admin"}}
45
53
  #
46
54
  # @example Deep nesting without initialization
47
55
  # stats = Hash.new_nested_hash
48
- # (stats[:server][:region][:us_east][:errors] = []) << "Some Error"
49
- # stats # => {server: {region: {us_east: {errors: ["Some Error"]}}}}
50
- #
51
- # @note While extremely convenient, be cautious with very deep structures
52
- # as this creates new hashes on demand for any key access
53
- #
54
- def self.new_nested_hash
55
- new { |hash, key| hash[key] = new_nested_hash }
56
+ # stats[:server][:region][:us_east][:errors] = ["Error"]
57
+ # stats # => {server: {region: {us_east: {errors: ["Error"]}}}}
58
+ #
59
+ # @example Limited nesting depth
60
+ # hash = Hash.new_nested_hash(depth: 1)
61
+ # hash[:user][:name] = "Alice" # Works fine - only one level of auto-creation
62
+ #
63
+ # # This pattern works correctly with limited nesting:
64
+ # (hash[:user][:roles] ||= []) << "admin"
65
+ # hash # => {user: {name: "Alice", roles: ["admin"]}}
66
+ #
67
+ # @note While unlimited nesting is convenient, it can interfere with common Ruby
68
+ # patterns like ||= when initializing values at deep depths. Use the depth
69
+ # parameter to control this behavior.
70
+ #
71
+ def self.new_nested_hash(depth: nil)
72
+ new do |hash, key|
73
+ next if depth == 0
74
+
75
+ hash[key] =
76
+ if depth.nil?
77
+ new_nested_hash
78
+ else
79
+ new_nested_hash(depth: depth - 1)
80
+ end
81
+ end
56
82
  end
57
83
 
58
84
  #
@@ -249,7 +275,7 @@ class Hash
249
275
  # # => {a: 2, b: 4}
250
276
  #
251
277
  # @example Using with_key to access keys during transformation
252
- # {a: 1, b: 2}.transform_values.with_key { |k, v| "#{k}_#{v}" }
278
+ # {a: 1, b: 2}.transform_values.with_key { |v, k| "#{k}_#{v}" }
253
279
  # # => {a: "a_1", b: "b_2"}
254
280
  #
255
281
  def transform_values(&block)
@@ -279,7 +305,7 @@ class Hash
279
305
  #
280
306
  # @example Using with_key to access keys during in-place transformation
281
307
  # hash = {a: 1, b: 2}
282
- # hash.transform_values!.with_key { |k, v| "#{k}_#{v}" }
308
+ # hash.transform_values!.with_key { |v, k| "#{k}_#{v}" }
283
309
  # # => {a: "a_1", b: "b_2"}
284
310
  #
285
311
  def transform_values!(&block)
@@ -288,6 +314,49 @@ class Hash
288
314
  og_transform_values!(&block)
289
315
  end
290
316
 
317
+ #
318
+ # Transforms keys and values to create a new hash
319
+ #
320
+ # @yield [key, value] Block that returns a new key-value pair
321
+ # @yieldparam key [Object] The original key
322
+ # @yieldparam value [Object] The original value
323
+ # @yieldreturn [Array] Two-element array containing the new key and value
324
+ #
325
+ # @return [Hash] A new hash with transformed keys and values
326
+ # @return [Enumerator] If no block is given
327
+ #
328
+ # @example Transform both keys and values
329
+ # {a: 1, b: 2}.transform { |k, v| ["#{k}_key", v * 2] }
330
+ # # => {a_key: 2, b_key: 4}
331
+ #
332
+ def transform(&block)
333
+ return to_enum(:transform) if block.nil?
334
+
335
+ to_h(&block)
336
+ end
337
+
338
+ #
339
+ # Transforms keys and values in place
340
+ #
341
+ # @yield [key, value] Block that returns a new key-value pair
342
+ # @yieldparam key [Object] The original key
343
+ # @yieldparam value [Object] The original value
344
+ # @yieldreturn [Array] Two-element array containing the new key and value
345
+ #
346
+ # @return [self] The transformed hash
347
+ # @return [Enumerator] If no block is given
348
+ #
349
+ # @example Transform both keys and values in place
350
+ # hash = {a: 1, b: 2}
351
+ # hash.transform! { |k, v| ["#{k}_key", v * 2] }
352
+ # # => {a_key: 2, b_key: 4}
353
+ #
354
+ def transform!(&block)
355
+ return to_enum(:transform!) if block.nil?
356
+
357
+ replace(transform(&block))
358
+ end
359
+
291
360
  #
292
361
  # Returns the first value where the key-value pair satisfies the given condition
293
362
  #
@@ -339,6 +408,127 @@ class Hash
339
408
  select(&block).values
340
409
  end
341
410
 
411
+ #
412
+ # Renames a key in the hash while preserving the original order of elements
413
+ #
414
+ # @param old_key [Object] The key to rename
415
+ # @param new_key [Object] The new key to use
416
+ #
417
+ # @return [Hash] A new hash with the key renamed
418
+ #
419
+ # @example Renames a single key
420
+ # {a: 1, b: 2, c: 3}.rename_key(:b, :middle)
421
+ # # => {a: 1, middle: 2, c: 3}
422
+ #
423
+ def rename_key(old_key, new_key)
424
+ rename_keys(old_key => new_key)
425
+ end
426
+
427
+ #
428
+ # Renames a key in the hash in place while preserving the original order of elements
429
+ #
430
+ # @param old_key [Object] The key to rename
431
+ # @param new_key [Object] The new key to use
432
+ #
433
+ # @return [self] The modified hash
434
+ #
435
+ # @example Renames a key in place
436
+ # hash = {a: 1, b: 2, c: 3}
437
+ # hash.rename_key!(:b, :middle)
438
+ # # => {a: 1, middle: 2, c: 3}
439
+ #
440
+ def rename_key!(old_key, new_key)
441
+ rename_keys!(old_key => new_key)
442
+ end
443
+
444
+ #
445
+ # Renames multiple keys in the hash while preserving the original order of elements
446
+ #
447
+ # This method maintains the original order of all keys in the hash, renaming
448
+ # only the specified keys while keeping their positions unchanged.
449
+ #
450
+ # @param keys [Hash] A mapping of old_key => new_key pairs
451
+ #
452
+ # @return [Hash] A new hash with keys renamed
453
+ #
454
+ # @example Renames multiple keys
455
+ # {a: 1, b: 2, c: 3, d: 4}.rename_keys(a: :first, c: :third)
456
+ # # => {first: 1, b: 2, third: 3, d: 4}
457
+ #
458
+ def rename_keys(**keys)
459
+ # I tried multiple different ways to rename the key while preserving the order, this was the fastest
460
+ transform_keys do |key|
461
+ keys.key?(key) ? keys[key] : key
462
+ end
463
+ end
464
+
465
+ #
466
+ # Renames multiple keys in the hash in place while preserving the original order of elements
467
+ #
468
+ # This method maintains the original order of all keys in the hash, renaming
469
+ # only the specified keys while keeping their positions unchanged.
470
+ #
471
+ # @param keys [Hash] A mapping of old_key => new_key pairs
472
+ #
473
+ # @return [self] The modified hash
474
+ #
475
+ # @example Rename multiple keys in place
476
+ # hash = {a: 1, b: 2, c: 3, d: 4}
477
+ # hash.rename_keys!(a: :first, c: :third)
478
+ # # => {first: 1, b: 2, third: 3, d: 4}
479
+ #
480
+ def rename_keys!(**keys)
481
+ # I tried multiple different ways to rename the key while preserving the order, this was the fastest
482
+ transform_keys! do |key|
483
+ keys.key?(key) ? keys[key] : key
484
+ end
485
+ end
486
+
487
+ #
488
+ # Renames a key in the hash without preserving element order (faster)
489
+ #
490
+ # This method is significantly faster than #rename_key but does not
491
+ # guarantee that the order of elements in the hash will be preserved.
492
+ #
493
+ # @param old_key [Object] The key to rename
494
+ # @param new_key [Object] The new key to use
495
+ #
496
+ # @return [Hash] A new hash with the key renamed
497
+ #
498
+ # @example Rename a single key without preserving order
499
+ # {a: 1, b: 2, c: 3}.rename_key_unordered(:b, :middle)
500
+ # # => {a: 1, c: 3, middle: 2} # Order may differ
501
+ #
502
+ def rename_key_unordered(old_key, new_key)
503
+ # Fun thing I learned. For small hashes, using #except is 1.5x faster than using dup and delete.
504
+ # But as the hash becomes larger, the performance improvements become diminished until they're roughly the same.
505
+ # Neat!
506
+ hash = except(old_key)
507
+ hash[new_key] = self[old_key]
508
+ hash
509
+ end
510
+
511
+ #
512
+ # Renames a key in the hash in place without preserving element order (faster)
513
+ #
514
+ # This method is significantly faster than #rename_key! but does not
515
+ # guarantee that the order of elements in the hash will be preserved.
516
+ #
517
+ # @param old_key [Object] The key to rename
518
+ # @param new_key [Object] The new key to use
519
+ #
520
+ # @return [self] The modified hash
521
+ #
522
+ # @example Rename a key in place without preserving order
523
+ # hash = {a: 1, b: 2, c: 3}
524
+ # hash.rename_key_unordered!(:b, :middle)
525
+ # # => {a: 1, c: 3, middle: 2} # Order may differ
526
+ #
527
+ def rename_key_unordered!(old_key, new_key)
528
+ self[new_key] = delete(old_key)
529
+ self
530
+ end
531
+
342
532
  private
343
533
 
344
534
  def transform_values_enumerator
@@ -350,7 +540,7 @@ class Hash
350
540
  raise ArgumentError, "Missing block for Hash#transform_values.with_key" if block.nil?
351
541
 
352
542
  original_hash.each_pair.with_object({}) do |(key, value), output|
353
- output[key] = block.call(key, value)
543
+ output[key] = block.call(value, key)
354
544
  end
355
545
  end
356
546
 
@@ -366,7 +556,7 @@ class Hash
366
556
  raise ArgumentError, "Missing block for Hash#transform_values!.with_key" if block.nil?
367
557
 
368
558
  original_hash.each_pair do |key, value|
369
- original_hash[key] = block.call(key, value)
559
+ original_hash[key] = block.call(value, key)
370
560
  end
371
561
 
372
562
  original_hash
@@ -3,10 +3,12 @@
3
3
  #
4
4
  # Extensions to Ruby's core Module class
5
5
  #
6
- # These additions provide a convenient way to create boolean-style accessor
7
- # methods for any class.
6
+ # Provides:
7
+ # - #attr_predicate: Create boolean-style accessor methods
8
+ #
9
+ # @example
10
+ # require "everythingrb/module"
8
11
  #
9
- # @example Creating predicate methods
10
12
  # class User
11
13
  # attr_accessor :admin
12
14
  # attr_predicate :admin
@@ -14,7 +16,7 @@
14
16
  #
15
17
  # user = User.new
16
18
  # user.admin = true
17
- # user.admin? # => true
19
+ # user.admin? # => true
18
20
  #
19
21
  class Module
20
22
  #
@@ -3,12 +3,17 @@
3
3
  #
4
4
  # Extensions to Ruby's OpenStruct class
5
5
  #
6
- # These additions make OpenStructs way more flexible with enumeration
7
- # methods and ActiveSupport integration.
6
+ # Provides:
7
+ # - #map, #filter_map: Enumeration methods for OpenStruct entries
8
+ # - #join_map: Combine filter_map and join operations
9
+ # - #blank?, #present?: ActiveSupport integrations when available
10
+ # - #to_deep_h: Recursively convert to hash with all nested objects
11
+ #
12
+ # @example
13
+ # require "everythingrb/ostruct"
8
14
  #
9
- # @example Using enumeration methods
10
15
  # person = OpenStruct.new(name: "Alice", age: 30)
11
- # person.map { |k, v| "#{k} is #{v}" } # => ["name is Alice", "age is 30"]
16
+ # person.map { |k, v| "#{k}: #{v}" } # => ["name: Alice", "age: 30"]
12
17
  #
13
18
  class OpenStruct
14
19
  # ActiveSupport integrations
@@ -105,4 +110,20 @@ class OpenStruct
105
110
  def to_ostruct
106
111
  self
107
112
  end
113
+
114
+ #
115
+ # Recursively converts the OpenStruct and all nested objects to hashes
116
+ #
117
+ # @return [Hash] A deeply converted hash of the OpenStruct
118
+ #
119
+ # @example
120
+ # person = OpenStruct.new(
121
+ # name: "Alice",
122
+ # address: OpenStruct.new(city: "New York", country: "USA")
123
+ # )
124
+ # person.to_deep_h # => {name: "Alice", address: {city: "New York", country: "USA"}}
125
+ #
126
+ def to_deep_h
127
+ to_h.to_deep_h
128
+ end
108
129
  end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ostruct"
4
+ require "json"
5
+
6
+ #
7
+ # EverythingRB - Super handy extensions to Ruby's core classes
8
+ #
9
+ # This gem enhances Ruby's built-in classes with useful methods that make
10
+ # your code more expressive and fun to write. Just require "everythingrb"
11
+ # and all the extensions are automatically available!
12
+ #
13
+ # @author Bryan "itsthedevman"
14
+ # @since 0.1.0
15
+ #
16
+ # @example Basic usage
17
+ # # In your Gemfile
18
+ # gem "everythingrb"
19
+ #
20
+ # # In your code
21
+ # require "everythingrb"
22
+ #
23
+ # # Now you have access to all the extensions!
24
+ # users = [{name: "Alice"}, {name: "Bob"}]
25
+ # users.key_map(:name).join(", ") # => "Alice, Bob"
26
+ #
27
+ module Everythingrb
28
+ end
29
+
30
+ require_relative "version"
@@ -3,14 +3,17 @@
3
3
  #
4
4
  # Extensions to Ruby's core String class
5
5
  #
6
- # These additions make working with JSON strings easy by providing methods for conversion
7
- # to various Ruby data structures. Plus some nice formatting helpers that saves tons of typing
6
+ # Provides:
7
+ # - #to_h, #to_a: Convert JSON strings to Hash/Array with error handling
8
+ # - #to_deep_h: Recursively parse nested JSON strings
9
+ # - #to_ostruct, #to_istruct, #to_struct: Convert JSON to data structures
10
+ # - #with_quotes, #in_quotes: Wrap strings in quotes
8
11
  #
9
- # @example Converting JSON to different structures
10
- # json = '{"user": {"name": "Alice", "admin": true}}'
11
- # json.to_h # => {user: {name: "Alice", admin: true}}
12
- # json.to_istruct.user.name # => "Alice"
13
- # json.to_ostruct.user.name # => "Alice"
12
+ # @example
13
+ # require "everythingrb/string"
14
+ #
15
+ # '{"user": {"name": "Alice"}}'.to_ostruct.user.name # => "Alice"
16
+ # "Hello".with_quotes # => "\"Hello\""
14
17
  #
15
18
  class String
16
19
  #
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Extensions to Ruby's core Struct class
5
+ #
6
+ # Provides:
7
+ # - #to_deep_h: Recursively convert to hash with all nested objects
8
+ #
9
+ # @example
10
+ # require "everythingrb/struct"
11
+ #
12
+ # Person = Struct.new(:name, :profile)
13
+ # person = Person.new("Alice", {roles: ["admin"]})
14
+ # person.to_deep_h # => {name: "Alice", profile: {roles: ["admin"]}}
15
+ #
16
+ class Struct
17
+ #
18
+ # Recursively converts the Struct and all nested objects to hashes
19
+ #
20
+ # @return [Hash] A deeply converted hash of the Struct
21
+ #
22
+ # @example
23
+ # Address = Struct.new(:city, :country)
24
+ # Person = Struct.new(:name, :address)
25
+ # person = Person.new("Alice", Address.new("New York", "USA"))
26
+ # person.to_deep_h # => {name: "Alice", address: {city: "New York", country: "USA"}}
27
+ #
28
+ def to_deep_h
29
+ to_h.to_deep_h
30
+ end
31
+ end
@@ -3,9 +3,12 @@
3
3
  #
4
4
  # Extensions to Ruby's core Symbol class
5
5
  #
6
- # These additions provide handy formatting helpers for symbols.
6
+ # Provides:
7
+ # - #with_quotes, #in_quotes: Wrap symbols in quotes
7
8
  #
8
9
  # @example
10
+ # require "everythingrb/symbol"
11
+ #
9
12
  # :hello_world.with_quotes # => :"\"hello_world\""
10
13
  #
11
14
  class Symbol
@@ -7,5 +7,5 @@
7
7
  #
8
8
  module Everythingrb
9
9
  # Current version of the everythingrb gem
10
- VERSION = "0.3.1"
10
+ VERSION = "0.5.0"
11
11
  end
data/lib/everythingrb.rb CHANGED
@@ -1,37 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "ostruct"
4
- require "json"
5
-
6
- require_relative "everythingrb/version"
7
- require_relative "everythingrb/core/array"
8
- require_relative "everythingrb/core/enumerable"
9
- require_relative "everythingrb/core/hash"
10
- require_relative "everythingrb/core/module"
11
- require_relative "everythingrb/core/ostruct"
12
- require_relative "everythingrb/core/string"
13
- require_relative "everythingrb/core/symbol"
14
-
15
- #
16
- # EverythingRB - Super handy extensions to Ruby's core classes
17
- #
18
- # This gem enhances Ruby's built-in classes with useful methods that make
19
- # your code more expressive and fun to write. Just require "everythingrb"
20
- # and all the extensions are automatically available!
21
- #
22
- # @author Bryan "itsthedevman"
23
- # @since 0.1.0
24
- #
25
- # @example Basic usage
26
- # # In your Gemfile
27
- # gem "everythingrb"
28
- #
29
- # # In your code
30
- # require "everythingrb"
31
- #
32
- # # Now you have access to all the extensions!
33
- # users = [{name: "Alice"}, {name: "Bob"}]
34
- # users.key_map(:name).join(", ") # => "Alice, Bob"
35
- #
36
- module Everythingrb
37
- end
3
+ require_relative "everythingrb/prelude"
4
+ require_relative "everythingrb/all"
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.3.1
4
+ version: 0.5.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-09 00:00:00.000000000 Z
11
+ date: 2025-04-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ostruct
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '2.9'
33
+ version: '2.10'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '2.9'
40
+ version: '2.10'
41
41
  description: EverythingRB extends Ruby core classes with useful methods for combining
42
42
  operations (join_map), converting data structures (to_struct, to_ostruct, to_istruct),
43
43
  and handling JSON with nested parsing support.
@@ -57,13 +57,17 @@ files:
57
57
  - flake.lock
58
58
  - flake.nix
59
59
  - lib/everythingrb.rb
60
- - lib/everythingrb/core/array.rb
61
- - lib/everythingrb/core/enumerable.rb
62
- - lib/everythingrb/core/hash.rb
63
- - lib/everythingrb/core/module.rb
64
- - lib/everythingrb/core/ostruct.rb
65
- - lib/everythingrb/core/string.rb
66
- - lib/everythingrb/core/symbol.rb
60
+ - lib/everythingrb/all.rb
61
+ - lib/everythingrb/array.rb
62
+ - lib/everythingrb/data.rb
63
+ - lib/everythingrb/enumerable.rb
64
+ - lib/everythingrb/hash.rb
65
+ - lib/everythingrb/module.rb
66
+ - lib/everythingrb/ostruct.rb
67
+ - lib/everythingrb/prelude.rb
68
+ - lib/everythingrb/string.rb
69
+ - lib/everythingrb/struct.rb
70
+ - lib/everythingrb/symbol.rb
67
71
  - lib/everythingrb/version.rb
68
72
  homepage: https://github.com/itsthedevman/everythingrb
69
73
  licenses: