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 +4 -4
- data/CHANGELOG.md +11 -0
- data/lib/everythingrb/all.rb +1 -0
- data/lib/everythingrb/datum.rb +64 -0
- data/lib/everythingrb/hash.rb +36 -12
- data/lib/everythingrb/string.rb +24 -3
- data/lib/everythingrb/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1dd9fbbf9f007e0996405d8689b8a288bc68968d0df0cf291a7a8a80a04c73b2
|
|
4
|
+
data.tar.gz: fa4d6d91ccfa3af739bc3726d406adec90215c639326741c18071d51dffae1aa
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
data/lib/everythingrb/all.rb
CHANGED
|
@@ -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
|
data/lib/everythingrb/hash.rb
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# Extensions to Ruby's core Hash class
|
|
5
5
|
#
|
|
6
6
|
# Provides:
|
|
7
|
-
# - #to_struct, #to_ostruct, #
|
|
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
|
-
#
|
|
77
|
+
# Recursively converts hash to an immutable Datum
|
|
78
78
|
#
|
|
79
|
-
#
|
|
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.
|
|
87
|
+
# data = hash.to_datum
|
|
84
88
|
# data.person.name # => "Bob"
|
|
85
|
-
# data.class # => Data
|
|
86
89
|
#
|
|
87
|
-
def
|
|
88
|
-
recurse = lambda do |
|
|
89
|
-
case
|
|
90
|
+
def to_datum
|
|
91
|
+
recurse = lambda do |value|
|
|
92
|
+
case value
|
|
90
93
|
when Hash
|
|
91
|
-
|
|
94
|
+
value.to_datum
|
|
92
95
|
when Array
|
|
93
|
-
|
|
96
|
+
value.map(&recurse)
|
|
94
97
|
else
|
|
95
|
-
|
|
98
|
+
value
|
|
96
99
|
end
|
|
97
100
|
end
|
|
98
101
|
|
|
99
|
-
|
|
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
|
#
|
data/lib/everythingrb/string.rb
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
#
|
|
6
6
|
# Provides:
|
|
7
7
|
# - #parse_json: Parse JSON strings with error handling
|
|
8
|
-
# - #to_ostruct, #
|
|
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
|
-
# @
|
|
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
|
-
|
|
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
|
#
|
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: 1.0
|
|
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-
|
|
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
|