everythingrb 0.6.1 → 0.8.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.
@@ -6,7 +6,6 @@
6
6
  # Provides:
7
7
  # - #join_map: Combine filter_map and join operations in one step
8
8
  # - #key_map, #dig_map: Extract values from arrays of hashes
9
- # - #deep_freeze: Recursively freeze array and contents
10
9
  # - #compact_prefix, #compact_suffix, #trim_nils: Clean up array boundaries
11
10
  # - ActiveSupport integrations: #trim_blanks and more when ActiveSupport is loaded
12
11
  #
@@ -16,6 +15,8 @@
16
15
  # [{name: "Alice"}, {name: "Bob"}].key_map(:name) # => ["Alice", "Bob"]
17
16
  #
18
17
  class Array
18
+ include Everythingrb::InspectQuotable
19
+
19
20
  #
20
21
  # Combines filter_map and join operations
21
22
  #
@@ -73,34 +74,17 @@ class Array
73
74
  # @return [Array] Array of nested values
74
75
  #
75
76
  # @example
76
- # [
77
+ # users = [
77
78
  # {user: {profile: {name: "Alice"}}},
78
79
  # {user: {profile: {name: "Bob"}}}
79
- # ].dig_map(:user, :profile, :name)
80
+ # ]
81
+ # users.dig_map(:user, :profile, :name)
80
82
  # # => ["Alice", "Bob"]
81
83
  #
82
84
  def dig_map(*keys)
83
85
  map { |v| v.dig(*keys) }
84
86
  end
85
87
 
86
- #
87
- # Recursively freezes self and all of its contents
88
- #
89
- # @return [self] Returns the frozen array
90
- #
91
- # @example Freeze an array with nested structures
92
- # ["hello", { name: "Alice" }, [1, 2, 3]].deep_freeze
93
- # # => All elements and nested structures are now frozen
94
- #
95
- # @note CAUTION: Be careful when freezing collections that contain class objects
96
- # or singleton instances - this will freeze those classes/objects globally!
97
- # Only use deep_freeze on pure data structures you want to make immutable.
98
- #
99
- def deep_freeze
100
- each { |v| v.respond_to?(:deep_freeze) ? v.deep_freeze : v.freeze }
101
- freeze
102
- end
103
-
104
88
  #
105
89
  # Removes nil values from the beginning of an array
106
90
  #
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Extensions to Ruby's core TrueClass
5
+ #
6
+ # Provides:
7
+ # - #in_quotes, #with_quotes: Wrap boolean values in quotes
8
+ #
9
+ # @example
10
+ # require "everythingrb/boolean"
11
+ #
12
+ # true.in_quotes # => "\"true\""
13
+ # false.in_quotes # => "\"false\""
14
+ #
15
+ class TrueClass
16
+ include Everythingrb::InspectQuotable
17
+ end
18
+
19
+ #
20
+ # Extensions to Ruby's core FalseClass
21
+ #
22
+ # Provides:
23
+ # - #in_quotes, #with_quotes: Wrap boolean values in quotes
24
+ #
25
+ # @example
26
+ # require "everythingrb/boolean"
27
+ #
28
+ # true.in_quotes # => "\"true\""
29
+ # false.in_quotes # => "\"false\""
30
+ #
31
+ class FalseClass
32
+ include Everythingrb::InspectQuotable
33
+ end
@@ -5,11 +5,18 @@
5
5
  #
6
6
  # Provides:
7
7
  # - #to_deep_h: Recursively convert to hash with all nested objects
8
+ # - #in_quotes, #with_quotes: Wrap object in quotes
8
9
  #
9
10
  class Data
11
+ include Everythingrb::InspectQuotable
12
+
10
13
  #
11
14
  # Recursively converts the Data object and all nested objects to hashes
12
15
  #
16
+ # This method traverses the entire Data structure, converting not just
17
+ # the top-level Data object but also nested Data objects, Structs, OpenStructs,
18
+ # and any other objects that implement `to_h`.
19
+ #
13
20
  # @return [Hash] A deeply converted hash of the Data object
14
21
  #
15
22
  # @example
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Extensions to Ruby's core Date class
5
+ #
6
+ # Provides:
7
+ # - #in_quotes, #with_quotes: Wrap date representations in quotes
8
+ #
9
+ # @example
10
+ # require "everythingrb/date"
11
+ #
12
+ # Date.today.in_quotes
13
+ #
14
+ class Date
15
+ include Everythingrb::StringQuotable
16
+ end
17
+
18
+ #
19
+ # Extensions to Ruby's core DateTime class
20
+ #
21
+ # Provides:
22
+ # - #in_quotes, #with_quotes: Wrap time representations in quotes
23
+ #
24
+ # @example
25
+ # require "everythingrb/date"
26
+ #
27
+ # DateTime.now.in_quotes
28
+ #
29
+ class DateTime < Date
30
+ include Everythingrb::StringQuotable
31
+ end
@@ -4,8 +4,8 @@
4
4
  # Extensions to Ruby's core Enumerable module
5
5
  #
6
6
  # Provides:
7
- # - #join_map: Combine filter_map and join operations
8
- # - #group_by_key: Group elements by a given key or nested keys
7
+ # - #join_map: Combine filter_map and join operations into one step
8
+ # - #group_by_key: Group elements by key or nested keys, simplifying collection organization
9
9
  #
10
10
  # @example
11
11
  # require "everythingrb/enumerable"
@@ -24,6 +24,7 @@ module Enumerable
24
24
  # @yieldparam index [Integer] The index of the current element (only if with_index: true)
25
25
  #
26
26
  # @return [String] Joined string of filtered and transformed elements
27
+ # @return [Enumerator] If no block is given
27
28
  #
28
29
  # @example Without index
29
30
  # [1, 2, nil, 3].join_map(" ") { |n| n&.to_s if n&.odd? }
@@ -57,6 +58,7 @@ module Enumerable
57
58
  # @yieldreturn [Object] The transformed value to use as the group key
58
59
  #
59
60
  # @return [Hash] A hash where keys are the grouped values and values are arrays of elements
61
+ # @return [Enumerator] If no block is given
60
62
  #
61
63
  # @example Group by a single key
62
64
  # users = [
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Extensions for making objects quotable with double quotes
5
+ #
6
+ # These modules add the ability to quote objects by wrapping
7
+ # their string representations in double quotes. This is useful for
8
+ # generating error messages, debug output, or formatted logs where
9
+ # you want to clearly distinguish between different value types.
10
+ #
11
+ # @example Basic usage with different types
12
+ # 1.in_quotes # => "\"1\""
13
+ # nil.in_quotes # => "\"nil\""
14
+ # "hello".in_quotes # => "\"\\\"hello\\\"\""
15
+ # [1, 2, 3].in_quotes # => "\"[1, 2, 3]\""
16
+ #
17
+ # @example Using with collections
18
+ # values = [1, nil, "hello"]
19
+ # values.map(&:in_quotes) # => ["\"1\"", "\"nil\"", "\"\\\"hello\\\"\""]
20
+ #
21
+ # @example Error messages
22
+ # expected = 42
23
+ # actual = nil
24
+ # raise "Expected #{expected.in_quotes} but got #{actual.in_quotes}"
25
+ # # => "Expected \"42\" but got \"nil\""
26
+ #
27
+ module Everythingrb
28
+ #
29
+ # Adds quotable functionality using inspect representation
30
+ #
31
+ # Provides methods for wrapping an object's inspection
32
+ # representation in double quotes.
33
+ #
34
+ # @example
35
+ # [1, 2, 3].in_quotes # => "\"[1, 2, 3]\""
36
+ #
37
+ module InspectQuotable
38
+ #
39
+ # Adds quotable functionality using inspect representation
40
+ #
41
+ # Provides methods for wrapping an object's inspection
42
+ # representation in double quotes.
43
+ #
44
+ # @return [String] The object's inspect representation surrounded by double quotes
45
+ #
46
+ # @example
47
+ # [1, 2, 3].in_quotes # => "\"[1, 2, 3]\""
48
+ # {a: 1}.in_quotes # => "\"{:a=>1}\""
49
+ #
50
+ def in_quotes
51
+ %("#{inspect}")
52
+ end
53
+
54
+ alias_method :with_quotes, :in_quotes
55
+ end
56
+
57
+ #
58
+ # Adds quotable functionality using to_s representation
59
+ #
60
+ # Provides methods for wrapping an object's string
61
+ # representation in double quotes.
62
+ #
63
+ # @example
64
+ # Time.now.in_quotes # => "\"2025-05-03 12:34:56 -0400\""
65
+ #
66
+ module StringQuotable
67
+ #
68
+ # Returns the object's string representation wrapped in double quotes
69
+ #
70
+ # @return [String] The object's to_s representation surrounded by double quotes
71
+ #
72
+ # @example
73
+ # Date.today.in_quotes # => "\"2025-05-03\""
74
+ # Time.now.in_quotes # => "\"2025-05-03 12:34:56 -0400\""
75
+ #
76
+ def in_quotes
77
+ %("#{self}")
78
+ end
79
+
80
+ alias_method :with_quotes, :in_quotes
81
+ end
82
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ Dir[File.expand_path("./extensions/**/*.rb", __dir__)].each { |path| require path }
@@ -6,12 +6,14 @@
6
6
  # Provides:
7
7
  # - #to_struct, #to_ostruct, #to_istruct: Convert hashes to different structures
8
8
  # - #join_map: Combine filter_map and join operations
9
- # - #deep_freeze: Recursively freeze hash and contents
10
9
  # - #transform_values.with_key: Transform values with access to keys
11
10
  # - #transform, #transform!: Transform keys and values
12
11
  # - #value_where, #values_where: Find values based on conditions
13
12
  # - #rename_key, #rename_keys: Rename hash keys while preserving order
14
13
  # - ::new_nested_hash: Create automatically nesting hashes
14
+ # - #merge_if, #merge_if!: Conditionally merge based on key-value pairs
15
+ # - #merge_if_values, #merge_if_values!: Conditionally merge based on values
16
+ # - #merge_compact, #merge_compact!: Merge only non-nil values
15
17
  #
16
18
  # @example
17
19
  # require "everythingrb/hash"
@@ -19,6 +21,8 @@
19
21
  # config.server.port # => 443
20
22
  #
21
23
  class Hash
24
+ include Everythingrb::InspectQuotable
25
+
22
26
  #
23
27
  # A minimal empty struct for Ruby 3.2+ compatibility
24
28
  #
@@ -46,6 +50,10 @@ class Hash
46
50
  #
47
51
  # @return [Hash] A hash that creates nested hashes for missing keys
48
52
  #
53
+ # @note This implementation is not thread-safe for concurrent modifications of deeply
54
+ # nested structures. If you need thread safety, consider using a mutex when modifying
55
+ # the deeper levels of the hash.
56
+ #
49
57
  # @example Unlimited nesting (default behavior)
50
58
  # users = Hash.new_nested_hash
51
59
  # users[:john][:role] = "admin" # No need to initialize users[:john] first
@@ -113,7 +121,7 @@ class Hash
113
121
  # and calls #to_h on any object that responds to it. Useful for
114
122
  # normalizing nested data structures and parsing nested JSON.
115
123
  #
116
- # @return [Hash] A deeply converted hash with all nested objects converted
124
+ # @return [Hash] A deeply converted hash with all nested objects
117
125
  #
118
126
  # @example Converting nested Data objects
119
127
  # user = { name: "Alice", metadata: Data.define(:source).new(source: "API") }
@@ -233,28 +241,10 @@ class Hash
233
241
  OpenStruct.new(**transform_values { |value| recurse.call(value) })
234
242
  end
235
243
 
236
- #
237
- # Recursively freezes self and all of its values
238
- #
239
- # @return [self] Returns the frozen hash
240
- #
241
- # @example
242
- # { user: { name: "Alice", roles: ["admin"] } }.deep_freeze
243
- # # => Hash and all nested structures are now frozen
244
- #
245
- # @note CAUTION: Be careful when freezing collections that contain class objects
246
- # or singleton instances - this will freeze those classes/objects globally!
247
- # Only use deep_freeze on pure data structures you want to make immutable.
248
- #
249
- def deep_freeze
250
- each_value { |v| v.respond_to?(:deep_freeze) ? v.deep_freeze : v.freeze }
251
- freeze
252
- end
253
-
254
- # Allows calling original method. See below
244
+ # @!visibility private
255
245
  alias_method :og_transform_values, :transform_values
256
246
 
257
- # Allows calling original method. See below
247
+ # @!visibility private
258
248
  alias_method :og_transform_values!, :transform_values!
259
249
 
260
250
  #
@@ -333,10 +323,10 @@ class Hash
333
323
 
334
324
  # ActiveSupport integrations
335
325
  if defined?(ActiveSupport)
336
- # Allows calling original method. See below
326
+ # @!visibility private
337
327
  alias_method :og_deep_transform_values, :deep_transform_values
338
328
 
339
- # Allows calling original method. See below
329
+ # @!visibility private
340
330
  alias_method :og_deep_transform_values!, :deep_transform_values!
341
331
 
342
332
  #
@@ -663,4 +653,237 @@ class Hash
663
653
  self[new_key] = delete(old_key)
664
654
  self
665
655
  end
656
+
657
+ #
658
+ # Selects hash entries based only on their values
659
+ #
660
+ # @yield [value] Block that determines whether to include the entry
661
+ # @yieldparam value [Object] The current value
662
+ # @yieldreturn [Boolean] Whether to include this entry
663
+ #
664
+ # @return [Hash] A new hash including only entries where the block returned truthy
665
+ # @return [Enumerator] If no block is given
666
+ #
667
+ # @example Filter to include only present values (with ActiveSupport)
668
+ # {name: "Alice", bio: nil, role: ""}.select_values(&:present?)
669
+ # # => {name: "Alice"}
670
+ #
671
+ # @example Filter using more complex logic
672
+ # {id: 1, count: 0, items: [1, 2, 3]}.select_values { |v| v.is_a?(Array) || v > 0 }
673
+ # # => {id: 1, items: [1, 2, 3]}
674
+ #
675
+ def select_values(&block)
676
+ return to_enum(:select_values) if block.nil?
677
+
678
+ select { |_k, v| block.call(v) }
679
+ end
680
+
681
+ alias_method :filter_values, :select_values
682
+
683
+ #
684
+ # Selects hash entries based only on their values, modifying the hash in place
685
+ #
686
+ # @yield [value] Block that determines whether to keep the entry
687
+ # @yieldparam value [Object] The current value
688
+ # @yieldreturn [Boolean] Whether to keep this entry
689
+ #
690
+ # @return [self, nil] The modified hash, or nil if no changes were made
691
+ # @return [Enumerator] If no block is given
692
+ #
693
+ # @example Remove entries with empty values (with ActiveSupport)
694
+ # hash = {name: "Alice", bio: nil, role: ""}
695
+ # hash.select_values!(&:present?)
696
+ # # => {name: "Alice"}
697
+ # # hash is now {name: "Alice"}
698
+ #
699
+ def select_values!(&block)
700
+ return to_enum(:select_values!) if block.nil?
701
+
702
+ select! { |_k, v| block.call(v) }
703
+ end
704
+
705
+ alias_method :filter_values!, :select_values!
706
+
707
+ #
708
+ # Rejects hash entries based only on their values
709
+ #
710
+ # @yield [value] Block that determines whether to exclude the entry
711
+ # @yieldparam value [Object] The current value
712
+ # @yieldreturn [Boolean] Whether to exclude this entry
713
+ #
714
+ # @return [Hash] A new hash excluding entries where the block returned truthy
715
+ # @return [Enumerator] If no block is given
716
+ #
717
+ # @example Remove blank values (with ActiveSupport)
718
+ # {name: "Alice", bio: nil, role: ""}.reject_values(&:blank?)
719
+ # # => {name: "Alice"}
720
+ #
721
+ # @example Remove specific types of values
722
+ # {id: 1, count: 0, items: [1, 2, 3]}.reject_values { |v| v.is_a?(Integer) && v == 0 }
723
+ # # => {id: 1, items: [1, 2, 3]}
724
+ #
725
+ def reject_values(&block)
726
+ return to_enum(:reject_values) if block.nil?
727
+
728
+ reject { |_k, v| block.call(v) }
729
+ end
730
+
731
+ #
732
+ # Rejects hash entries based only on their values, modifying the hash in place
733
+ #
734
+ # @yield [value] Block that determines whether to remove the entry
735
+ # @yieldparam value [Object] The current value
736
+ # @yieldreturn [Boolean] Whether to remove this entry
737
+ #
738
+ # @return [self, nil] The modified hash, or nil if no changes were made
739
+ # @return [Enumerator] If no block is given
740
+ #
741
+ # @example Remove blank values in place (with ActiveSupport)
742
+ # hash = {name: "Alice", bio: nil, role: ""}
743
+ # hash.reject_values!(&:blank?)
744
+ # # => {name: "Alice"}
745
+ # # hash is now {name: "Alice"}
746
+ #
747
+ def reject_values!(&block)
748
+ return to_enum(:reject_values!) if block.nil?
749
+
750
+ reject! { |_k, v| block.call(v) }
751
+ end
752
+
753
+ #
754
+ # Conditionally merges key-value pairs from another hash based on a block
755
+ #
756
+ # @param other [Hash] The hash to merge from
757
+ #
758
+ # @yield [key, value] Block that determines whether to include each key-value pair
759
+ # @yieldparam key [Object] The key from the other hash
760
+ # @yieldparam value [Object] The value from the other hash
761
+ # @yieldreturn [Boolean] Whether to include this key-value pair
762
+ #
763
+ # @return [Hash] A new hash with conditionally merged key-value pairs
764
+ #
765
+ # @example Merge only even-numbered keys
766
+ # {a: 1, b: 2}.merge_if(c: 3, d: 4) { |key, _| key.to_s.ord.even? }
767
+ # # => {a: 1, b: 2, d: 4}
768
+ #
769
+ # @example Merge only positive values
770
+ # {a: 1, b: 2}.merge_if(c: 3, d: -4) { |_, value| value > 0 }
771
+ # # => {a: 1, b: 2, c: 3}
772
+ #
773
+ def merge_if(other = {}, &block)
774
+ other = other.select(&block) unless block.nil?
775
+
776
+ merge(other)
777
+ end
778
+
779
+ #
780
+ # Conditionally merges key-value pairs from another hash in place
781
+ #
782
+ # @param other [Hash] The hash to merge from
783
+ #
784
+ # @yield [key, value] Block that determines whether to include each key-value pair
785
+ # @yieldparam key [Object] The key from the other hash
786
+ # @yieldparam value [Object] The value from the other hash
787
+ # @yieldreturn [Boolean] Whether to include this key-value pair
788
+ #
789
+ # @return [self] The modified hash
790
+ #
791
+ # @example Merge only even-numbered keys in place
792
+ # hash = {a: 1, b: 2}
793
+ # hash.merge_if!(c: 3, d: 4) { |key, _| key.to_s.ord.even? }
794
+ # # => {a: 1, b: 2, d: 4}
795
+ #
796
+ def merge_if!(other = {}, &block)
797
+ other = other.select(&block) unless block.nil?
798
+
799
+ merge!(other)
800
+ end
801
+
802
+ #
803
+ # Conditionally merges key-value pairs based only on values
804
+ #
805
+ # @param other [Hash] The hash to merge from
806
+ #
807
+ # @yield [value] Block that determines whether to include each value
808
+ # @yieldparam value [Object] The value from the other hash
809
+ # @yieldreturn [Boolean] Whether to include this value
810
+ #
811
+ # @return [Hash] A new hash with conditionally merged values
812
+ #
813
+ # @example Merge only string values
814
+ # {a: 1, b: "old"}.merge_if_values(c: "new", d: 2) { |v| v.is_a?(String) }
815
+ # # => {a: 1, b: "old", c: "new"}
816
+ #
817
+ def merge_if_values(other = {}, &block)
818
+ merge_if(other) { |k, v| block.call(v) }
819
+ end
820
+
821
+ #
822
+ # Conditionally merges key-value pairs based only on values, in place
823
+ #
824
+ # @param other [Hash] The hash to merge from
825
+ #
826
+ # @yield [value] Block that determines whether to include each value
827
+ # @yieldparam value [Object] The value from the other hash
828
+ # @yieldreturn [Boolean] Whether to include this value
829
+ #
830
+ # @return [self] The modified hash
831
+ #
832
+ # @example Merge only numeric values in place
833
+ # hash = {a: 1, b: "text"}
834
+ # hash.merge_if_values!(c: "ignore", d: 2) { |v| v.is_a?(Numeric) }
835
+ # # => {a: 1, b: "text", d: 2}
836
+ #
837
+ def merge_if_values!(other = {}, &block)
838
+ merge_if!(other) { |k, v| block.call(v) }
839
+ end
840
+
841
+ #
842
+ # Merges only non-nil values from another hash
843
+ #
844
+ # This is a convenience method for the common pattern of merging
845
+ # only values that are not nil.
846
+ #
847
+ # @param other [Hash] The hash to merge from
848
+ #
849
+ # @return [Hash] A new hash with non-nil values merged
850
+ #
851
+ # @example Merge only non-nil values (common when building parameters)
852
+ # user_id = 42
853
+ # email = nil
854
+ # name = "Alice"
855
+ #
856
+ # {}.merge_compact(
857
+ # id: user_id,
858
+ # email: email,
859
+ # name: name
860
+ # )
861
+ # # => {id: 42, name: "Alice"}
862
+ #
863
+ def merge_compact(other = {})
864
+ merge_if_values(other, &:itself)
865
+ end
866
+
867
+ #
868
+ # Merges only non-nil values from another hash, in place
869
+ #
870
+ # This is a convenience method for the common pattern of merging
871
+ # only values that are not nil.
872
+ #
873
+ # @param other [Hash] The hash to merge from
874
+ #
875
+ # @return [self] The modified hash
876
+ #
877
+ # @example Merge only non-nil values in place
878
+ # params = {format: "json"}
879
+ # params.merge_compact!(
880
+ # page: 1,
881
+ # per_page: nil,
882
+ # sort: "created_at"
883
+ # )
884
+ # # => {format: "json", page: 1, sort: "created_at"}
885
+ #
886
+ def merge_compact!(other = {})
887
+ merge_if_values!(other, &:itself)
888
+ end
666
889
  end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Extensions to Ruby's core Kernel module
5
+ #
6
+ # Provides:
7
+ # - #morph: A more intuitive alias for Kernel#then (yield_self)
8
+ #
9
+ # @example
10
+ # require "everythingrb/kernel"
11
+ #
12
+ # # Instead of:
13
+ # config.fetch(:key).then { |v| process(v) }
14
+ #
15
+ # # More expressive with morph:
16
+ # config.fetch(:key).morph { |v| process(v) }
17
+ #
18
+ module Kernel
19
+ #
20
+ # Transforms the receiver by passing it to the given block and returning the block's result
21
+ #
22
+ # This method is an alias for `then` (and `yield_self`) that more clearly communicates
23
+ # the transformation intent.
24
+ #
25
+ # @yield [receiver] Block that transforms the receiver
26
+ # @yieldparam receiver [Object] The receiver object
27
+ # @yieldreturn [Object] The transformed result
28
+ #
29
+ # @return [Object] The result of the block
30
+ #
31
+ # @example Convert a semantic version to a string
32
+ # version.to_sem_version.morph { |v| "#{v.major}.#{v.minor}" }
33
+ #
34
+ alias_method :morph, :then
35
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Extensions to Ruby's NilClass
5
+ #
6
+ # Provides:
7
+ # - #in_quotes, #with_quotes: Wrap nil's string representation in quotes
8
+ #
9
+ # @example
10
+ # require "everythingrb/nil"
11
+ # nil.in_quotes # => "\"nil\""
12
+ #
13
+ class NilClass
14
+ include Everythingrb::InspectQuotable
15
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Extensions to Ruby's core Numeric class and subclasses
5
+ #
6
+ # Provides:
7
+ # - #in_quotes, #with_quotes: Wrap numeric values in quotes
8
+ #
9
+ # @example
10
+ # require "everythingrb/numeric"
11
+ #
12
+ # 42.in_quotes # => "\"42\""
13
+ # 3.14.in_quotes # => "\"3.14\""
14
+ # (1+2i).in_quotes # => "\"1+2i\""
15
+ #
16
+ class Numeric
17
+ include Everythingrb::InspectQuotable
18
+ end
@@ -8,6 +8,7 @@
8
8
  # - #join_map: Combine filter_map and join operations
9
9
  # - #blank?, #present?: ActiveSupport integrations when available
10
10
  # - #to_deep_h: Recursively convert to hash with all nested objects
11
+ # - #in_quotes, #with_quotes: Wrap struct in quotes
11
12
  #
12
13
  # @example
13
14
  # require "everythingrb/ostruct"
@@ -16,6 +17,8 @@
16
17
  # person.map { |k, v| "#{k}: #{v}" } # => ["name: Alice", "age: 30"]
17
18
  #
18
19
  class OpenStruct
20
+ include Everythingrb::InspectQuotable
21
+
19
22
  # ActiveSupport integrations
20
23
  if defined?(ActiveSupport)
21
24
  #
@@ -23,6 +26,8 @@ class OpenStruct
23
26
  #
24
27
  # @return [Boolean] true if the OpenStruct has no attributes
25
28
  #
29
+ # @note Only available when ActiveSupport is loaded
30
+ #
26
31
  def blank?
27
32
  @table.blank?
28
33
  end
@@ -30,7 +35,9 @@ class OpenStruct
30
35
  #
31
36
  # Checks if the OpenStruct has any attributes
32
37
  #
33
- # @return [Boolean] true if the OpenStruct has attributes
38
+ # @return [Boolean] true if the OpenStruct has any attributes
39
+ #
40
+ # @note Only available when ActiveSupport is loaded
34
41
  #
35
42
  def present?
36
43
  @table.present?
@@ -114,6 +121,9 @@ class OpenStruct
114
121
  #
115
122
  # Recursively converts the OpenStruct and all nested objects to hashes
116
123
  #
124
+ # This method will convert the OpenStruct and all nested OpenStructs,
125
+ # Structs, Data objects, and other convertible objects to plain hashes.
126
+ #
117
127
  # @return [Hash] A deeply converted hash of the OpenStruct
118
128
  #
119
129
  # @example