everythingrb 1.0.2 → 1.1.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: 7d4d1ff4ff501fb2c458bf0d23207db00f048f87337651a9acbb32fac3130892
4
- data.tar.gz: fef2dcb4bca0bbb191173456278766deb3718105fd74fbda82c14e95ca05381a
3
+ metadata.gz: 1dd9fbbf9f007e0996405d8689b8a288bc68968d0df0cf291a7a8a80a04c73b2
4
+ data.tar.gz: fa4d6d91ccfa3af739bc3726d406adec90215c639326741c18071d51dffae1aa
5
5
  SHA512:
6
- metadata.gz: 3b010d9ad8a8816cee802e130d8559bfd52bd2928973fb5af78d85700837ccc5fbdc0652f546450c5b8f466d92ee694edef3f66b8337176c2e05070f5ddd9e22
7
- data.tar.gz: 74038bc5467bb76fc296015f631fce28c4a5a533f8630794d1fc68f0215b8a29bcc9f7d1d4329d2140b9811dfe4db2f8bc6312bbbf272432051dd4a52cd9330c
6
+ metadata.gz: 2cf84c56c48419113d3736d5702ba9cfc918cbf5e1ff49277f024505ec190f60d5db5b727520ae7e16d39498173b1c8b7c39df9243ba65474632c1604db3dd3b
7
+ data.tar.gz: 316b7b50250d7538d9ae6635ae7df4f95a4e774ae652f6a4c4b6ec5e7405f9f5c06e8917ee63e20f421c2c73556d3f5baa8555746f73c6531ba9036ce79a53ea
data/CHANGELOG.md CHANGED
@@ -15,6 +15,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
15
15
  ### Removed
16
16
  -->
17
17
 
18
+ ## [1.1.0] - 12026-07-19
19
+
20
+ ### Added
21
+
22
+ - **Added `Datum`** - an immutable, dot-notation value object built in a single call (e.g. `Datum.new(host: "localhost", port: 3000)`). Think of it as the sealed counterpart to OpenStruct: OpenStruct's ergonomics with Data's immutability. Values are stored as-is, so it's immutable at the top level only. Unlike a bare `Data.define(...)`, Datums compare by attributes, so two Datums with the same members and values are equal and hash alike.
23
+ - **Added `Hash#to_datum` and `String#to_datum`** - convert into a `Datum`, recursing through nested hashes and arrays. These replace the deprecated `#to_istruct`.
24
+
25
+ ### Deprecated
26
+
27
+ - **Deprecated `Hash#to_istruct` and `String#to_istruct`** - use `#to_datum` instead. Both still work but now emit a deprecation warning, and will be removed in v2.0.0.
28
+
18
29
  ## [1.0.2] - 12026-05-30
19
30
 
20
31
  ### Changed
@@ -3,6 +3,7 @@
3
3
  require_relative "array"
4
4
  require_relative "boolean"
5
5
  require_relative "data"
6
+ require_relative "datum"
6
7
  require_relative "date"
7
8
  require_relative "enumerable"
8
9
  require_relative "hash"
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # An immutable, dot-notation object built from attributes in a single call
5
+ #
6
+ # Think of it as the sealed counterpart to OpenStruct: the ergonomics of OpenStruct.new(hash) with the
7
+ # immutability of Data. Values are stored as-is (nested hashes and arrays are left untouched), so the object is
8
+ # immutable only at the top level. Use Hash#to_datum when you want the conversion to recurse.
9
+ #
10
+ # @example Build an object inline
11
+ # config = Datum.new(host: "localhost", port: 3000)
12
+ # config.host # => "localhost"
13
+ #
14
+ # @example Nested data is left as-is
15
+ # data = Datum.new(name: "Bob", meta: {role: "admin"})
16
+ # data.meta # => {role: "admin"} (still a Hash)
17
+ #
18
+ # @example Structural equality
19
+ # Datum.new(a: 1) == Datum.new(a: 1) # => true
20
+ #
21
+ class Datum < Data
22
+ #
23
+ # Builds an immutable object from the given attributes
24
+ #
25
+ # @param attributes [Hash] The members and their values for the new object
26
+ #
27
+ # @return [Datum] An object whose members match the given keys
28
+ #
29
+ # @example
30
+ # Datum.new(host: "localhost", port: 3000)
31
+ #
32
+ def self.new(attributes = {})
33
+ define(*attributes.keys.map(&:to_sym)).new(*attributes.values)
34
+ end
35
+
36
+ #
37
+ # Compares against another Datum by attributes rather than by class
38
+ #
39
+ # Every Datum is backed by its own anonymous Data class, so the default
40
+ # comparison (which requires an identical class) would never match. This
41
+ # compares the underlying attributes instead.
42
+ #
43
+ # @param other [Object] The object to compare against
44
+ #
45
+ # @return [Boolean] True when other is a Datum with equal attributes
46
+ #
47
+ def ==(other)
48
+ other.is_a?(Datum) && to_h == other.to_h
49
+ end
50
+
51
+ alias_method :eql?, :==
52
+
53
+ #
54
+ # Returns a hash code derived from the attributes
55
+ #
56
+ # Keeps #hash consistent with #eql? so equal Datums collapse to the same
57
+ # Hash key or Set member.
58
+ #
59
+ # @return [Integer]
60
+ #
61
+ def hash
62
+ to_h.hash
63
+ end
64
+ end
@@ -4,7 +4,7 @@
4
4
  # Extensions to Ruby's core Hash class
5
5
  #
6
6
  # Provides:
7
- # - #to_struct, #to_ostruct, #to_istruct: Convert hashes to different structures
7
+ # - #to_struct, #to_ostruct, #to_datum: Convert hashes to different structures (#to_istruct is deprecated, use #to_datum)
8
8
  # - #join_map: Combine filter_map and join operations
9
9
  # - #transform_values.with_key: Transform values with access to keys
10
10
  # - #transform, #transform!: Transform keys and values
@@ -74,29 +74,53 @@ class Hash
74
74
  end
75
75
 
76
76
  #
77
- # Converts hash to an immutable Data structure
77
+ # Recursively converts hash to an immutable Datum
78
78
  #
79
- # @return [Data] An immutable Data object with the same structure
79
+ # Nested hashes and arrays are converted too. Unlike a raw Data object, two
80
+ # Datums with the same attributes are equal, so the result is safe to compare
81
+ # or use as a Hash key.
82
+ #
83
+ # @return [Datum] An immutable object mirroring the hash structure
80
84
  #
81
85
  # @example
82
86
  # hash = { person: { name: "Bob", age: 30 } }
83
- # data = hash.to_istruct
87
+ # data = hash.to_datum
84
88
  # data.person.name # => "Bob"
85
- # data.class # => Data
86
89
  #
87
- def to_istruct
88
- recurse = lambda do |input|
89
- case input
90
+ def to_datum
91
+ recurse = lambda do |value|
92
+ case value
90
93
  when Hash
91
- input.to_istruct
94
+ value.to_datum
92
95
  when Array
93
- input.map(&recurse)
96
+ value.map(&recurse)
94
97
  else
95
- input
98
+ value
96
99
  end
97
100
  end
98
101
 
99
- Data.define(*keys.map(&:to_sym)).new(*values.map { |value| recurse.call(value) })
102
+ Datum.new(transform_values { |value| recurse.call(value) })
103
+ end
104
+
105
+ #
106
+ # Recursively converts hash to an immutable Data structure
107
+ #
108
+ # @deprecated Use {#to_datum} instead. Will be removed in v2.0.0.
109
+ #
110
+ # @return [Datum] An immutable object mirroring the hash structure
111
+ #
112
+ # @example
113
+ # hash = { person: { name: "Bob", age: 30 } }
114
+ # data = hash.to_istruct
115
+ # data.person.name # => "Bob"
116
+ #
117
+ def to_istruct
118
+ Everythingrb.deprecator.warn(
119
+ "Hash#to_istruct is deprecated and will be removed in v2.0.0. " \
120
+ "Use Hash#to_datum instead."
121
+ )
122
+
123
+ to_datum
100
124
  end
101
125
 
102
126
  #
@@ -5,7 +5,7 @@
5
5
  #
6
6
  # Provides:
7
7
  # - #parse_json: Parse JSON strings with error handling
8
- # - #to_ostruct, #to_istruct, #to_struct: Convert JSON to data structures
8
+ # - #to_ostruct, #to_datum, #to_struct: Convert JSON to data structures (#to_istruct is deprecated, use #to_datum)
9
9
  # - #with_quotes, #in_quotes: Wrap strings in quotes
10
10
  # - #to_camelcase: Convert strings to camelCase or PascalCase
11
11
  #
@@ -52,18 +52,39 @@ class String
52
52
  nil
53
53
  end
54
54
 
55
+ #
56
+ # Attempts to parse JSON and convert to an immutable Datum.
57
+ # Returns nil if string does not contain valid JSON
58
+ #
59
+ # @return [Datum, nil] Immutable object or nil if invalid JSON
60
+ #
61
+ # @example
62
+ # '{"name": "Alice"}'.to_datum # => #<data name="Alice">
63
+ # "not json".to_datum # => nil
64
+ #
65
+ def to_datum
66
+ parse_json&.to_datum
67
+ end
68
+
55
69
  #
56
70
  # Attempts to parse JSON and convert to Data struct.
57
71
  # Returns nil if string does not contain valid JSON
58
72
  #
59
- # @return [Data, nil] Immutable Data structure or nil if invalid JSON
73
+ # @deprecated Use {#to_datum} instead. Will be removed in v2.0.0.
74
+ #
75
+ # @return [Datum, nil] Immutable object or nil if invalid JSON
60
76
  #
61
77
  # @example
62
78
  # '{"name": "Alice"}'.to_istruct # => #<data name="Alice">
63
79
  # "not json".to_istruct # => nil
64
80
  #
65
81
  def to_istruct
66
- parse_json&.to_istruct
82
+ Everythingrb.deprecator.warn(
83
+ "String#to_istruct is deprecated and will be removed in v2.0.0. " \
84
+ "Use String#to_datum instead."
85
+ )
86
+
87
+ parse_json&.to_datum
67
88
  end
68
89
 
69
90
  #
@@ -7,5 +7,5 @@
7
7
  #
8
8
  module Everythingrb
9
9
  # Current version of the everythingrb gem
10
- VERSION = "1.0.2"
10
+ VERSION = "1.1.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: 1.0.2
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bryan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-05-30 00:00:00.000000000 Z
11
+ date: 2026-07-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ostruct
@@ -72,6 +72,7 @@ files:
72
72
  - lib/everythingrb/boolean.rb
73
73
  - lib/everythingrb/data.rb
74
74
  - lib/everythingrb/date.rb
75
+ - lib/everythingrb/datum.rb
75
76
  - lib/everythingrb/enumerable.rb
76
77
  - lib/everythingrb/extensions.rb
77
78
  - lib/everythingrb/extensions/quotable.rb