dry-struct 1.3.0 → 1.7.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 +102 -5
- data/LICENSE +1 -1
- data/README.md +6 -13
- data/dry-struct.gemspec +19 -22
- data/lib/dry/struct/class_interface.rb +65 -88
- data/lib/dry/struct/compiler.rb +0 -3
- data/lib/dry/struct/errors.rb +4 -4
- data/lib/dry/struct/extensions/pretty_print.rb +6 -6
- data/lib/dry/struct/extensions.rb +1 -1
- data/lib/dry/struct/hashify.rb +3 -3
- data/lib/dry/struct/printer.rb +1 -1
- data/lib/dry/struct/struct_builder.rb +21 -13
- data/lib/dry/struct/sum.rb +6 -11
- data/lib/dry/struct/value.rb +3 -6
- data/lib/dry/struct/version.rb +1 -1
- data/lib/dry/struct.rb +49 -31
- data/lib/dry-struct.rb +1 -1
- metadata +19 -80
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fd8d3f0f41192daff14ed892da9e9a86e3dddefc4f7f94f26f58e1d091257532
|
4
|
+
data.tar.gz: 88d94467b25ec8f3a0e6f897232829ffbfb1ee3a1c1ec331e60ce3d5c386cb72
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a3d3a0a161d2a81053e7081a1d2deeead9a565c64a432350145c79083c58e400a8ed984e70b06388128c615d335cbccb29cb43b48f2669830bbf238064965c9e
|
7
|
+
data.tar.gz: 4c6a1a4c1a47f7b941e33c10ad515ce96247bae7e916088863a56c8c1104de5e4344b7314150eeb774627778c76fb79b6f209ba554627786a02ec918f7cf43df
|
data/CHANGELOG.md
CHANGED
@@ -1,9 +1,87 @@
|
|
1
|
+
<!--- DO NOT EDIT THIS FILE - IT'S AUTOMATICALLY GENERATED VIA DEVTOOLS --->
|
2
|
+
|
3
|
+
## 1.7.0 2025-01-06
|
4
|
+
|
5
|
+
|
6
|
+
### Fixed
|
7
|
+
|
8
|
+
- Fixed coercion errors for structs (issue #192 via #193) (@flash-gordon)
|
9
|
+
- Invalid method names are now allowed as struct attributes (issue #169 via #195) (@flash-gordon)
|
10
|
+
|
11
|
+
### Changed
|
12
|
+
|
13
|
+
- Missing attribute error now includes the name of the class (issue #170 via #191) (@phillipoertel + @cllns)
|
14
|
+
- 3.1 is now the minimum Ruby version (@flash-gordon)
|
15
|
+
- `Dry::Struct::Error` is now a subclass of `Dry::Types::CoercionError` (in #193) (@flash-gordon)
|
16
|
+
- `Dry::Struct#[]` now returns `nil` if an optional attribute is not set. This is consistent with calling accessor methods for optional attributes. (issue #171 via #194) (@ivleonov + @flash-gordon)
|
17
|
+
|
18
|
+
[Compare v1.6.0...v1.7.0](https://github.com/dry-rb/dry-struct/compare/v1.6.0...v1.7.0)
|
19
|
+
|
20
|
+
## 1.6.0 2022-11-04
|
21
|
+
|
22
|
+
|
23
|
+
### Changed
|
24
|
+
|
25
|
+
- This version uses dry-core 1.0 (@flash-gordon + @solnic)
|
26
|
+
|
27
|
+
[Compare v1.5.2...v1.6.0](https://github.com/dry-rb/dry-struct/compare/v1.5.2...v1.6.0)
|
28
|
+
|
29
|
+
## 1.5.2 2022-10-19
|
30
|
+
|
31
|
+
|
32
|
+
### Fixed
|
33
|
+
|
34
|
+
- Coercion failures keep the original error instead of just having a string (@flash-gordon + @newx)
|
35
|
+
|
36
|
+
|
37
|
+
[Compare v1.5.1...v1.5.2](https://github.com/dry-rb/dry-struct/compare/v1.5.1...v1.5.2)
|
38
|
+
|
39
|
+
## 1.5.1 2022-10-17
|
40
|
+
|
41
|
+
|
42
|
+
### Fixed
|
43
|
+
|
44
|
+
- Fixed issues with auto-loading `Extensions` module (issue #183 fixed via #184) (@solnic)
|
45
|
+
|
46
|
+
|
47
|
+
[Compare v1.5.0...v1.5.1](https://github.com/dry-rb/dry-struct/compare/v1.5.0...v1.5.1)
|
48
|
+
|
49
|
+
## 1.5.0 2022-10-15
|
50
|
+
|
51
|
+
|
52
|
+
### Changed
|
53
|
+
|
54
|
+
- Use zeitwerk for auto-loading (@flash-gordon)
|
55
|
+
|
56
|
+
[Compare v1.4.0...v1.5.0](https://github.com/dry-rb/dry-struct/compare/v1.4.0...v1.5.0)
|
57
|
+
|
58
|
+
## 1.4.0 2021-01-21
|
59
|
+
|
60
|
+
|
61
|
+
### Added
|
62
|
+
|
63
|
+
- Support for wrapping constructors and fallbacks, see release notes for dry-types 1.5.0 (@flash-gordon)
|
64
|
+
- Improvements of the attribute DSL, now it's possible to use optional structs as a base class (@flash-gordon)
|
65
|
+
```ruby
|
66
|
+
class User < Dry::Struct
|
67
|
+
attribute :name, Types::String
|
68
|
+
attribute :address, Dry::Struct.optional do
|
69
|
+
attribute :city, Types::String
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
User.new(name: "John", address: nil) # => #<User name="John" address=nil>
|
74
|
+
```
|
75
|
+
|
76
|
+
|
77
|
+
[Compare v1.3.0...v1.4.0](https://github.com/dry-rb/dry-struct/compare/v1.3.0...v1.4.0)
|
78
|
+
|
1
79
|
## 1.3.0 2020-02-10
|
2
80
|
|
3
81
|
|
4
82
|
### Added
|
5
83
|
|
6
|
-
- Nested structures will reuse type and key transformations from
|
84
|
+
- Nested structures will reuse type and key transformations from the enclosing struct (@flash-gordon)
|
7
85
|
|
8
86
|
```ruby
|
9
87
|
class User < Dry::Struct
|
@@ -22,13 +100,32 @@
|
|
22
100
|
end
|
23
101
|
end
|
24
102
|
```
|
25
|
-
- `Dry::Struct::Constructor` finally acts like a fully-featured type (flash-gordon)
|
26
|
-
- `Dry::Struct.abstract` declares a struct class as abstract. An abstract class is used as a default superclass for nested structs (flash-gordon)
|
27
|
-
- `Struct.to_ast` and struct compiler (@flash-gordon)
|
103
|
+
- `Dry::Struct::Constructor` finally acts like a fully-featured type (@flash-gordon)
|
104
|
+
- `Dry::Struct.abstract` declares a struct class as abstract. An abstract class is used as a default superclass for nested structs (@flash-gordon)
|
105
|
+
- `Dry::Struct.to_ast` and struct compiler (@flash-gordon)
|
106
|
+
- Struct composition with `Dry::Struct.attributes_from`. It's more flexible than inheritance (@waiting-for-dev + @flash-gordon)
|
107
|
+
|
108
|
+
```ruby
|
109
|
+
class Address < Dry::Struct
|
110
|
+
attribute :city, Types::String
|
111
|
+
attribute :zipcode, Types::String
|
112
|
+
end
|
113
|
+
|
114
|
+
class Buyer < Dry::Struct
|
115
|
+
attribute :name, Types::String
|
116
|
+
attributes_from Address
|
117
|
+
end
|
118
|
+
|
119
|
+
class Seller < Dry::Struct
|
120
|
+
attribute :name, Types::String
|
121
|
+
attribute :email, Types::String
|
122
|
+
attributes_from Address
|
123
|
+
end
|
124
|
+
```
|
28
125
|
|
29
126
|
### Changed
|
30
127
|
|
31
|
-
- [internal] metadata is now stored inside schema (flash-gordon)
|
128
|
+
- [internal] metadata is now stored inside schema (@flash-gordon)
|
32
129
|
|
33
130
|
[Compare v1.2.0...v1.3.0](https://github.com/dry-rb/dry-struct/compare/v1.2.0...v1.3.0)
|
34
131
|
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -1,28 +1,21 @@
|
|
1
|
+
<!--- this file is synced from dry-rb/template-gem project -->
|
1
2
|
[gem]: https://rubygems.org/gems/dry-struct
|
2
3
|
[actions]: https://github.com/dry-rb/dry-struct/actions
|
3
|
-
[codacy]: https://www.codacy.com/gh/dry-rb/dry-struct
|
4
|
-
[chat]: https://dry-rb.zulipchat.com
|
5
|
-
[inchpages]: http://inch-ci.org/github/dry-rb/dry-struct
|
6
4
|
|
7
|
-
# dry-struct [][gem]
|
10
|
-
[][actions]
|
11
|
-
[][codacy]
|
12
|
-
[][codacy]
|
13
|
-
[][inchpages]
|
5
|
+
# dry-struct [][gem] [][actions]
|
14
6
|
|
15
7
|
## Links
|
16
8
|
|
17
|
-
* [User documentation](
|
9
|
+
* [User documentation](https://dry-rb.org/gems/dry-struct)
|
18
10
|
* [API documentation](http://rubydoc.info/gems/dry-struct)
|
11
|
+
* [Forum](https://discourse.dry-rb.org)
|
19
12
|
|
20
13
|
## Supported Ruby versions
|
21
14
|
|
22
15
|
This library officially supports the following Ruby versions:
|
23
16
|
|
24
|
-
* MRI
|
25
|
-
* jruby
|
17
|
+
* MRI `>= 3.1`
|
18
|
+
* jruby `>= 9.4` (not tested on CI)
|
26
19
|
|
27
20
|
## License
|
28
21
|
|
data/dry-struct.gemspec
CHANGED
@@ -1,40 +1,37 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
# this file is managed by dry-rb/devtools project
|
3
2
|
|
4
|
-
|
3
|
+
# this file is synced from dry-rb/template-gem project
|
4
|
+
|
5
|
+
lib = File.expand_path("lib", __dir__)
|
5
6
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
6
|
-
require
|
7
|
+
require "dry/struct/version"
|
7
8
|
|
8
9
|
Gem::Specification.new do |spec|
|
9
|
-
spec.name =
|
10
|
+
spec.name = "dry-struct"
|
10
11
|
spec.authors = ["Piotr Solnica"]
|
11
12
|
spec.email = ["piotr.solnica@gmail.com"]
|
12
|
-
spec.license =
|
13
|
+
spec.license = "MIT"
|
13
14
|
spec.version = Dry::Struct::VERSION.dup
|
14
15
|
|
15
16
|
spec.summary = "Typed structs and value objects"
|
16
17
|
spec.description = spec.summary
|
17
|
-
spec.homepage =
|
18
|
+
spec.homepage = "https://dry-rb.org/gems/dry-struct"
|
18
19
|
spec.files = Dir["CHANGELOG.md", "LICENSE", "README.md", "dry-struct.gemspec", "lib/**/*"]
|
19
|
-
spec.bindir =
|
20
|
+
spec.bindir = "bin"
|
20
21
|
spec.executables = []
|
21
|
-
spec.require_paths = [
|
22
|
+
spec.require_paths = ["lib"]
|
22
23
|
|
23
|
-
spec.metadata[
|
24
|
-
spec.metadata[
|
25
|
-
spec.metadata[
|
26
|
-
spec.metadata[
|
24
|
+
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
25
|
+
spec.metadata["changelog_uri"] = "https://github.com/dry-rb/dry-struct/blob/main/CHANGELOG.md"
|
26
|
+
spec.metadata["source_code_uri"] = "https://github.com/dry-rb/dry-struct"
|
27
|
+
spec.metadata["bug_tracker_uri"] = "https://github.com/dry-rb/dry-struct/issues"
|
28
|
+
spec.metadata["rubygems_mfa_required"] = "true"
|
27
29
|
|
28
|
-
spec.required_ruby_version = ">=
|
30
|
+
spec.required_ruby_version = ">= 3.1.0"
|
29
31
|
|
30
32
|
# to update dependencies edit project.yml
|
31
|
-
spec.
|
32
|
-
spec.
|
33
|
-
spec.
|
34
|
-
spec.
|
35
|
-
|
36
|
-
spec.add_development_dependency "bundler"
|
37
|
-
spec.add_development_dependency "rake"
|
38
|
-
spec.add_development_dependency "rspec"
|
39
|
-
spec.add_development_dependency "yard"
|
33
|
+
spec.add_dependency "dry-core", "~> 1.1"
|
34
|
+
spec.add_dependency "dry-types", "~> 1.8"
|
35
|
+
spec.add_dependency "ice_nine", "~> 0.11"
|
36
|
+
spec.add_dependency "zeitwerk", "~> 2.6"
|
40
37
|
end
|
@@ -1,32 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require 'dry/core/class_attributes'
|
5
|
-
require 'dry/core/inflector'
|
6
|
-
require 'dry/core/descendants_tracker'
|
7
|
-
|
8
|
-
require 'dry/struct/errors'
|
9
|
-
require 'dry/struct/constructor'
|
10
|
-
require 'dry/struct/sum'
|
3
|
+
require "weakref"
|
11
4
|
|
12
5
|
module Dry
|
13
6
|
class Struct
|
14
7
|
# Class-level interface of {Struct} and {Value}
|
15
|
-
module ClassInterface
|
8
|
+
module ClassInterface # rubocop:disable Metrics/ModuleLength
|
16
9
|
include Core::ClassAttributes
|
17
10
|
|
18
11
|
include Types::Type
|
19
12
|
include Types::Builder
|
20
13
|
|
21
|
-
# @param [Class] klass
|
22
|
-
def inherited(klass)
|
23
|
-
super
|
24
|
-
|
25
|
-
unless klass.name.eql?('Dry::Struct::Value')
|
26
|
-
klass.extend(Core::DescendantsTracker)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
14
|
# Adds an attribute for this {Struct} with given `name` and `type`
|
31
15
|
# and modifies {.schema} accordingly.
|
32
16
|
#
|
@@ -49,8 +33,12 @@ module Dry
|
|
49
33
|
# end
|
50
34
|
# end
|
51
35
|
#
|
52
|
-
# Language.schema
|
53
|
-
# # => #<Dry::Types[
|
36
|
+
# Language.schema # new lines for readability
|
37
|
+
# # => #<Dry::Types[
|
38
|
+
# Constructor<Schema<keys={
|
39
|
+
# name: Constrained<Nominal<String> rule=[type?(String)]>
|
40
|
+
# details: Language::Details
|
41
|
+
# }> fn=Kernel.Hash>]>
|
54
42
|
#
|
55
43
|
# ruby = Language.new(name: 'Ruby', details: { type: 'OO' })
|
56
44
|
# ruby.name #=> 'Ruby'
|
@@ -67,10 +55,12 @@ module Dry
|
|
67
55
|
# end
|
68
56
|
# end
|
69
57
|
#
|
70
|
-
# Language.schema
|
58
|
+
# Language.schema # new lines for readability
|
71
59
|
# => #<Dry::Types[Constructor<Schema<keys={
|
72
60
|
# name: Constrained<Nominal<String> rule=[type?(String)]>
|
73
|
-
# versions: Constrained<
|
61
|
+
# versions: Constrained<
|
62
|
+
# Array<Constrained<Nominal<String> rule=[type?(String)]>
|
63
|
+
# > rule=[type?(Array)]>
|
74
64
|
# celebrities: Constrained<Array<Language::Celebrity> rule=[type?(Array)]>
|
75
65
|
# }> fn=Kernel.Hash>]>
|
76
66
|
#
|
@@ -93,8 +83,8 @@ module Dry
|
|
93
83
|
# ruby.celebrities[0].pseudonym #=> 'Matz'
|
94
84
|
# ruby.celebrities[1].name #=> 'Aaron Patterson'
|
95
85
|
# ruby.celebrities[1].pseudonym #=> 'tenderlove'
|
96
|
-
def attribute(name, type = Undefined, &
|
97
|
-
attributes(name => build_type(name, type, &
|
86
|
+
def attribute(name, type = Undefined, &)
|
87
|
+
attributes(name => build_type(name, type, &))
|
98
88
|
end
|
99
89
|
|
100
90
|
# Add atributes from another struct
|
@@ -122,13 +112,13 @@ module Dry
|
|
122
112
|
#
|
123
113
|
# @param struct [Dry::Struct]
|
124
114
|
def attributes_from(struct)
|
125
|
-
extracted_schema = struct.schema.keys.
|
115
|
+
extracted_schema = struct.schema.keys.to_h do |key|
|
126
116
|
if key.required?
|
127
117
|
[key.name, key.type]
|
128
118
|
else
|
129
119
|
[:"#{key.name}?", key.type]
|
130
120
|
end
|
131
|
-
|
121
|
+
end
|
132
122
|
attributes(extracted_schema)
|
133
123
|
end
|
134
124
|
|
@@ -146,19 +136,19 @@ module Dry
|
|
146
136
|
# @param [Dry::Types::Type, nil] type or superclass of nested type
|
147
137
|
# @return [Dry::Struct]
|
148
138
|
#
|
149
|
-
def attribute?(*args, &
|
150
|
-
if args.size == 1 &&
|
139
|
+
def attribute?(*args, &)
|
140
|
+
if args.size == 1 && !block_given?
|
151
141
|
Core::Deprecations.warn(
|
152
|
-
|
153
|
-
|
154
|
-
tag: :
|
142
|
+
"Dry::Struct.attribute? is deprecated for checking attribute presence, " \
|
143
|
+
"use has_attribute? instead",
|
144
|
+
tag: :"dry-struct"
|
155
145
|
)
|
156
146
|
|
157
147
|
has_attribute?(args[0])
|
158
148
|
else
|
159
149
|
name, * = args
|
160
150
|
|
161
|
-
attribute(:"#{name}?", build_type(*args, &
|
151
|
+
attribute(:"#{name}?", build_type(*args, &))
|
162
152
|
end
|
163
153
|
end
|
164
154
|
|
@@ -181,7 +171,7 @@ module Dry
|
|
181
171
|
# # author: Constrained<Nominal<String> rule=[type?(String)]>
|
182
172
|
# # }> fn=Kernel.Hash>]>
|
183
173
|
def attributes(new_schema)
|
184
|
-
keys = new_schema.keys.map { |k| k.to_s.chomp(
|
174
|
+
keys = new_schema.keys.map { |k| k.to_s.chomp("?").to_sym }
|
185
175
|
check_schema_duplication(keys)
|
186
176
|
|
187
177
|
schema schema.schema(new_schema)
|
@@ -190,9 +180,8 @@ module Dry
|
|
190
180
|
|
191
181
|
@attribute_names = nil
|
192
182
|
|
193
|
-
|
194
|
-
|
195
|
-
inherited_attrs = new_schema.reject { |k, _| d.has_attribute?(k.to_s.chomp('?').to_sym) }
|
183
|
+
subclasses.each do |d|
|
184
|
+
inherited_attrs = new_schema.reject { |k, _| d.has_attribute?(k.to_s.chomp("?").to_sym) }
|
196
185
|
d.attributes(inherited_attrs)
|
197
186
|
end
|
198
187
|
|
@@ -233,7 +222,7 @@ module Dry
|
|
233
222
|
schema schema.with_key_transform(proc || block)
|
234
223
|
end
|
235
224
|
|
236
|
-
# @param [Hash{Symbol => Dry::Types::Type, Dry::Struct}]
|
225
|
+
# @param [Hash{Symbol => Dry::Types::Type, Dry::Struct}] new_keys
|
237
226
|
# @raise [RepeatedAttributeError] when trying to define attribute with the
|
238
227
|
# same name as previously defined one
|
239
228
|
def check_schema_duplication(new_keys)
|
@@ -247,7 +236,7 @@ module Dry
|
|
247
236
|
|
248
237
|
# @param [Hash{Symbol => Object},Dry::Struct] attributes
|
249
238
|
# @raise [Struct::Error] if the given attributes don't conform {#schema}
|
250
|
-
def new(attributes = default_attributes, safe = false, &
|
239
|
+
def new(attributes = default_attributes, safe = false, &) # rubocop:disable Style/OptionalBooleanParameter
|
251
240
|
if attributes.is_a?(Struct)
|
252
241
|
if equal?(attributes.class)
|
253
242
|
attributes
|
@@ -257,23 +246,23 @@ module Dry
|
|
257
246
|
# User.new(super_user)
|
258
247
|
#
|
259
248
|
# We may deprecate this behavior in future forcing people to be explicit
|
260
|
-
new(attributes.to_h, safe, &
|
249
|
+
new(attributes.to_h, safe, &)
|
261
250
|
end
|
262
251
|
elsif safe
|
263
252
|
load(schema.call_safe(attributes) { |output = attributes| return yield output })
|
264
253
|
else
|
265
254
|
load(schema.call_unsafe(attributes))
|
266
255
|
end
|
267
|
-
rescue Types::CoercionError =>
|
268
|
-
raise Error, "[#{self}.new] #{
|
256
|
+
rescue Types::CoercionError => e
|
257
|
+
raise Error, "[#{self}.new] #{e}", e.backtrace
|
269
258
|
end
|
270
259
|
|
271
260
|
# @api private
|
272
|
-
def call_safe(input, &
|
261
|
+
def call_safe(input, &)
|
273
262
|
if input.is_a?(self)
|
274
263
|
input
|
275
264
|
else
|
276
|
-
new(input, true, &
|
265
|
+
new(input, true, &)
|
277
266
|
end
|
278
267
|
end
|
279
268
|
|
@@ -289,7 +278,7 @@ module Dry
|
|
289
278
|
# @api private
|
290
279
|
def load(attributes)
|
291
280
|
struct = allocate
|
292
|
-
struct.
|
281
|
+
struct.__send__(:initialize, attributes)
|
293
282
|
struct
|
294
283
|
end
|
295
284
|
|
@@ -297,17 +286,17 @@ module Dry
|
|
297
286
|
# @param [#call,nil] block
|
298
287
|
# @return [Dry::Struct::Constructor]
|
299
288
|
def constructor(constructor = nil, **, &block)
|
300
|
-
Constructor
|
289
|
+
Constructor[self, fn: constructor || block]
|
301
290
|
end
|
302
291
|
|
303
292
|
# @param [Hash{Symbol => Object},Dry::Struct] input
|
304
293
|
# @yieldparam [Dry::Types::Result::Failure] failure
|
305
|
-
# @yieldreturn [Dry::Types::
|
294
|
+
# @yieldreturn [Dry::Types::Result]
|
306
295
|
# @return [Dry::Types::Result]
|
307
296
|
def try(input)
|
308
297
|
success(self[input])
|
309
298
|
rescue Error => e
|
310
|
-
failure_result = failure(input, e
|
299
|
+
failure_result = failure(input, e)
|
311
300
|
block_given? ? yield(failure_result) : failure_result
|
312
301
|
end
|
313
302
|
|
@@ -324,48 +313,32 @@ module Dry
|
|
324
313
|
|
325
314
|
# @param [({Symbol => Object})] args
|
326
315
|
# @return [Dry::Types::Result::Success]
|
327
|
-
def success(*args)
|
328
|
-
result(Types::Result::Success, *args)
|
329
|
-
end
|
316
|
+
def success(*args) = result(Types::Result::Success, *args)
|
330
317
|
|
331
318
|
# @param [({Symbol => Object})] args
|
332
319
|
# @return [Dry::Types::Result::Failure]
|
333
|
-
def failure(*args)
|
334
|
-
result(Types::Result::Failure, *args)
|
335
|
-
end
|
320
|
+
def failure(*args) = result(Types::Result::Failure, *args)
|
336
321
|
|
337
322
|
# @param [Class] klass
|
338
323
|
# @param [({Symbol => Object})] args
|
339
|
-
def result(klass, *args)
|
340
|
-
klass.new(*args)
|
341
|
-
end
|
324
|
+
def result(klass, *args) = klass.new(*args)
|
342
325
|
|
343
326
|
# @return [false]
|
344
|
-
def default?
|
345
|
-
false
|
346
|
-
end
|
327
|
+
def default? = false
|
347
328
|
|
348
|
-
# @param [Object, Dry::Struct]
|
329
|
+
# @param [Object, Dry::Struct] other
|
349
330
|
# @return [Boolean]
|
350
|
-
def ===(other)
|
351
|
-
other.is_a?(self)
|
352
|
-
end
|
331
|
+
def ===(other) = other.is_a?(self)
|
353
332
|
alias_method :primitive?, :===
|
354
333
|
|
355
334
|
# @return [true]
|
356
|
-
def constrained?
|
357
|
-
true
|
358
|
-
end
|
335
|
+
def constrained? = true
|
359
336
|
|
360
337
|
# @return [self]
|
361
|
-
def primitive
|
362
|
-
self
|
363
|
-
end
|
338
|
+
def primitive = self
|
364
339
|
|
365
340
|
# @return [false]
|
366
|
-
def optional?
|
367
|
-
false
|
368
|
-
end
|
341
|
+
def optional? = false
|
369
342
|
|
370
343
|
# @return [Proc]
|
371
344
|
def to_proc
|
@@ -376,9 +349,7 @@ module Dry
|
|
376
349
|
#
|
377
350
|
# @param [Symbol] key Attribute name
|
378
351
|
# @return [Boolean]
|
379
|
-
def has_attribute?(key)
|
380
|
-
schema.key?(key)
|
381
|
-
end
|
352
|
+
def has_attribute?(key) = schema.key?(key)
|
382
353
|
|
383
354
|
# Gets the list of attribute names
|
384
355
|
#
|
@@ -456,39 +427,45 @@ module Dry
|
|
456
427
|
# Constructs a type
|
457
428
|
#
|
458
429
|
# @return [Dry::Types::Type, Dry::Struct]
|
459
|
-
def build_type(name, type = Undefined, &
|
430
|
+
def build_type(name, type = Undefined, &)
|
460
431
|
type_object =
|
461
432
|
if type.is_a?(::String)
|
462
433
|
Types[type]
|
463
|
-
elsif
|
434
|
+
elsif !block_given? && Undefined.equal?(type)
|
464
435
|
raise(
|
465
436
|
::ArgumentError,
|
466
|
-
|
437
|
+
"you must supply a type or a block to `Dry::Struct.attribute`"
|
467
438
|
)
|
468
439
|
else
|
469
440
|
type
|
470
441
|
end
|
471
442
|
|
472
|
-
if
|
473
|
-
struct_builder.(name, type_object, &
|
443
|
+
if block_given?
|
444
|
+
struct_builder.(name, type_object, &)
|
474
445
|
else
|
475
446
|
type_object
|
476
447
|
end
|
477
448
|
end
|
478
449
|
private :build_type
|
479
450
|
|
451
|
+
# @api private
|
480
452
|
def define_accessors(keys)
|
481
|
-
keys.each do |key|
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
453
|
+
(keys - instance_methods).each do |key|
|
454
|
+
if valid_method_name?(key)
|
455
|
+
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
456
|
+
def #{key} # def email
|
457
|
+
@attributes[#{key.inspect}] # @attributes[:email]
|
458
|
+
end # end
|
459
|
+
RUBY
|
460
|
+
else
|
461
|
+
define_method(key) { @attributes[key] }
|
462
|
+
end
|
489
463
|
end
|
490
464
|
end
|
491
465
|
private :define_accessors
|
466
|
+
|
467
|
+
# @api private
|
468
|
+
private def valid_method_name?(key) = key.to_s.match?(/\A[a-zA-Z_]\w*\z/)
|
492
469
|
end
|
493
470
|
end
|
494
471
|
end
|
data/lib/dry/struct/compiler.rb
CHANGED
data/lib/dry/struct/errors.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
module Dry
|
4
4
|
class Struct
|
5
5
|
# Raised when given input doesn't conform schema and constructor type
|
6
|
-
Error = Class.new(
|
6
|
+
Error = Class.new(::Dry::Types::CoercionError)
|
7
7
|
|
8
8
|
# Raised when defining duplicate attributes
|
9
9
|
class RepeatedAttributeError < ::ArgumentError
|
@@ -16,8 +16,8 @@ module Dry
|
|
16
16
|
|
17
17
|
# Raised when a struct doesn't have an attribute
|
18
18
|
class MissingAttributeError < ::KeyError
|
19
|
-
def initialize(
|
20
|
-
super("Missing attribute: #{
|
19
|
+
def initialize(attribute:, klass:)
|
20
|
+
super("Missing attribute: #{attribute.inspect} on #{klass}")
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
@@ -25,7 +25,7 @@ module Dry
|
|
25
25
|
# This shouldn't happen in a working application
|
26
26
|
class RecycledStructError < ::RuntimeError
|
27
27
|
def initialize
|
28
|
-
super(
|
28
|
+
super("Reference to struct class was garbage collected")
|
29
29
|
end
|
30
30
|
end
|
31
31
|
end
|
@@ -1,18 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "pp"
|
4
4
|
|
5
5
|
module Dry
|
6
6
|
class Struct
|
7
7
|
def pretty_print(pp)
|
8
8
|
klass = self.class
|
9
|
-
pp.group(1, "#<#{klass.name || klass.inspect}",
|
10
|
-
pp.seplist(@attributes.keys, proc { pp.text
|
9
|
+
pp.group(1, "#<#{klass.name || klass.inspect}", ">") do
|
10
|
+
pp.seplist(@attributes.keys, proc { pp.text "," }) do |column_name|
|
11
11
|
column_value = @attributes[column_name]
|
12
|
-
pp.breakable
|
12
|
+
pp.breakable " "
|
13
13
|
pp.group(1) do
|
14
|
-
pp.text column_name
|
15
|
-
pp.text
|
14
|
+
pp.text column_name.to_s
|
15
|
+
pp.text "="
|
16
16
|
pp.pp column_value
|
17
17
|
end
|
18
18
|
end
|
data/lib/dry/struct/hashify.rb
CHANGED
@@ -9,11 +9,11 @@ module Dry
|
|
9
9
|
# @return [Hash, Array]
|
10
10
|
def self.[](value)
|
11
11
|
if value.is_a?(Struct)
|
12
|
-
value.to_h.transform_values {
|
12
|
+
value.to_h.transform_values { self[_1] }
|
13
13
|
elsif value.respond_to?(:to_hash)
|
14
|
-
value.to_hash.transform_values {
|
14
|
+
value.to_hash.transform_values { self[_1] }
|
15
15
|
elsif value.respond_to?(:to_ary)
|
16
|
-
value.to_ary.map {
|
16
|
+
value.to_ary.map { self[_1] }
|
17
17
|
else
|
18
18
|
value
|
19
19
|
end
|
data/lib/dry/struct/printer.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'dry/struct/compiler'
|
4
|
-
|
5
3
|
module Dry
|
6
4
|
class Struct
|
7
5
|
# @private
|
@@ -14,9 +12,10 @@ module Dry
|
|
14
12
|
end
|
15
13
|
|
16
14
|
# @param [Symbol|String] attr_name the name of the nested type
|
17
|
-
# @param [Dry::Struct,Dry::Types::Type::Array,Undefined] type the superclass
|
15
|
+
# @param [Dry::Struct,Dry::Types::Type::Array,Undefined] type the superclass
|
16
|
+
# of the nested struct
|
18
17
|
# @yield the body of the nested struct
|
19
|
-
def call(attr_name, type, &
|
18
|
+
def call(attr_name, type, &)
|
20
19
|
const_name = const_name(type, attr_name)
|
21
20
|
check_name(const_name)
|
22
21
|
|
@@ -28,12 +27,15 @@ module Dry
|
|
28
27
|
schema builder.struct.schema.clear
|
29
28
|
end
|
30
29
|
|
31
|
-
class_exec(&
|
30
|
+
class_exec(&)
|
32
31
|
end
|
32
|
+
|
33
33
|
struct.const_set(const_name, new_type)
|
34
34
|
|
35
35
|
if array?(type)
|
36
36
|
type.of(new_type)
|
37
|
+
elsif optional?(type)
|
38
|
+
new_type.optional
|
37
39
|
else
|
38
40
|
new_type
|
39
41
|
end
|
@@ -41,13 +43,19 @@ module Dry
|
|
41
43
|
|
42
44
|
private
|
43
45
|
|
46
|
+
def type?(type) = type.is_a?(Types::Type)
|
47
|
+
|
44
48
|
def array?(type)
|
45
|
-
type
|
49
|
+
type?(type) && !type.optional? && type.primitive.equal?(::Array)
|
46
50
|
end
|
47
51
|
|
52
|
+
def optional?(type) = type?(type) && type.optional?
|
53
|
+
|
48
54
|
def parent(type)
|
49
55
|
if array?(type)
|
50
56
|
visit(type.to_ast)
|
57
|
+
elsif optional?(type)
|
58
|
+
type.right
|
51
59
|
else
|
52
60
|
type
|
53
61
|
end
|
@@ -65,10 +73,12 @@ module Dry
|
|
65
73
|
end
|
66
74
|
|
67
75
|
def check_name(name)
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
76
|
+
if struct.const_defined?(name, false)
|
77
|
+
raise(
|
78
|
+
Error,
|
79
|
+
"Can't create nested attribute - `#{struct}::#{name}` already defined"
|
80
|
+
)
|
81
|
+
end
|
72
82
|
end
|
73
83
|
|
74
84
|
def visit_constrained(node)
|
@@ -81,9 +91,7 @@ module Dry
|
|
81
91
|
visit(member)
|
82
92
|
end
|
83
93
|
|
84
|
-
def visit_nominal(*)
|
85
|
-
Undefined
|
86
|
-
end
|
94
|
+
def visit_nominal(*) = Undefined
|
87
95
|
|
88
96
|
def visit_constructor(node)
|
89
97
|
definition, * = node
|
data/lib/dry/struct/sum.rb
CHANGED
@@ -1,8 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'dry/types/sum'
|
4
|
-
require 'dry/types/printer'
|
5
|
-
|
6
3
|
module Dry
|
7
4
|
class Struct
|
8
5
|
# A sum type of two or more structs
|
@@ -17,11 +14,11 @@ module Dry
|
|
17
14
|
|
18
15
|
# @param [Hash{Symbol => Object},Dry::Struct] input
|
19
16
|
# @yieldparam [Dry::Types::Result::Failure] failure
|
20
|
-
# @yieldreturn [Dry::Types::
|
17
|
+
# @yieldreturn [Dry::Types::Result]
|
21
18
|
# @return [Dry::Types::Result]
|
22
19
|
def try(input)
|
23
20
|
if input.is_a?(Struct)
|
24
|
-
try_struct(input) { super }
|
21
|
+
::Dry::Types::Result::Success.new(try_struct(input) { return super })
|
25
22
|
else
|
26
23
|
super
|
27
24
|
end
|
@@ -31,7 +28,7 @@ module Dry
|
|
31
28
|
# @param [Dry::Types::Type] type
|
32
29
|
# @return [Dry::Types::Sum]
|
33
30
|
def |(type)
|
34
|
-
if type.is_a?(Class) && type <= Struct || type.is_a?(Sum)
|
31
|
+
if (type.is_a?(::Class) && type <= Struct) || type.is_a?(Sum)
|
35
32
|
Sum.new(self, type)
|
36
33
|
else
|
37
34
|
super
|
@@ -39,16 +36,14 @@ module Dry
|
|
39
36
|
end
|
40
37
|
|
41
38
|
# @return [boolean]
|
42
|
-
def ===(value)
|
43
|
-
left === value || right === value
|
44
|
-
end
|
39
|
+
def ===(value) = left === value || right === value
|
45
40
|
|
46
41
|
protected
|
47
42
|
|
48
43
|
# @private
|
49
|
-
def try_struct(input)
|
44
|
+
def try_struct(input, &)
|
50
45
|
left.try_struct(input) do
|
51
|
-
right.try_struct(input)
|
46
|
+
right.try_struct(input, &)
|
52
47
|
end
|
53
48
|
end
|
54
49
|
end
|
data/lib/dry/struct/value.rb
CHANGED
@@ -1,11 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require 'dry/core/deprecations'
|
3
|
+
require "ice_nine"
|
5
4
|
|
6
5
|
module Dry
|
7
6
|
class Struct
|
8
|
-
extend Core::Deprecations[:
|
7
|
+
extend Core::Deprecations[:"dry-struct"]
|
9
8
|
|
10
9
|
# {Value} objects behave like {Struct}s but *deeply frozen*
|
11
10
|
# using [`ice_nine`](https://github.com/dkubb/ice_nine)
|
@@ -30,9 +29,7 @@ module Dry
|
|
30
29
|
# @param (see ClassInterface#new)
|
31
30
|
# @return [Value]
|
32
31
|
# @see https://github.com/dkubb/ice_nine
|
33
|
-
def self.new(*)
|
34
|
-
::IceNine.deep_freeze(super)
|
35
|
-
end
|
32
|
+
def self.new(*) = ::IceNine.deep_freeze(super)
|
36
33
|
end
|
37
34
|
|
38
35
|
deprecate_constant :Value
|
data/lib/dry/struct/version.rb
CHANGED
data/lib/dry/struct.rb
CHANGED
@@ -1,16 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
|
5
|
-
require
|
6
|
-
require
|
7
|
-
|
8
|
-
|
9
|
-
require
|
10
|
-
require
|
11
|
-
require 'dry/struct/class_interface'
|
12
|
-
require 'dry/struct/hashify'
|
13
|
-
require 'dry/struct/struct_builder'
|
3
|
+
require "weakref"
|
4
|
+
|
5
|
+
require "dry/core"
|
6
|
+
require "dry/types"
|
7
|
+
|
8
|
+
require "dry/struct/class_interface"
|
9
|
+
require "dry/struct/errors"
|
10
|
+
require "dry/struct/version"
|
14
11
|
|
15
12
|
module Dry
|
16
13
|
# Constructor method for easily creating a {Dry::Struct}.
|
@@ -30,10 +27,10 @@ module Dry
|
|
30
27
|
# Test = Dry.Struct(expected: Types::String) { schema(schema.strict) }
|
31
28
|
# Test[expected: "foo", unexpected: "bar"]
|
32
29
|
# #=> Dry::Struct::Error: [Test.new] unexpected keys [:unexpected] in Hash input
|
33
|
-
def self.Struct(attributes = Dry::Core::Constants::EMPTY_HASH, &
|
30
|
+
def self.Struct(attributes = Dry::Core::Constants::EMPTY_HASH, &)
|
34
31
|
Class.new(Dry::Struct) do
|
35
32
|
attributes.each { |a, type| attribute a, type }
|
36
|
-
module_eval(&
|
33
|
+
module_eval(&) if block_given?
|
37
34
|
end
|
38
35
|
end
|
39
36
|
|
@@ -88,21 +85,35 @@ module Dry
|
|
88
85
|
extend Core::Extensions
|
89
86
|
include Core::Constants
|
90
87
|
extend ClassInterface
|
91
|
-
extend Core::Deprecations[:
|
88
|
+
extend Core::Deprecations[:"dry-struct"]
|
92
89
|
|
93
90
|
class << self
|
94
91
|
# override `Dry::Types::Builder#prepend`
|
95
92
|
define_method(:prepend, ::Module.method(:prepend))
|
93
|
+
|
94
|
+
def loader
|
95
|
+
@loader ||= ::Zeitwerk::Loader.new.tap do |loader|
|
96
|
+
root = ::File.expand_path("..", __dir__)
|
97
|
+
loader.tag = "dry-struct"
|
98
|
+
loader.inflector = ::Zeitwerk::GemInflector.new("#{root}/dry-struct.rb")
|
99
|
+
loader.push_dir(root)
|
100
|
+
loader.ignore(
|
101
|
+
"#{root}/dry-struct.rb",
|
102
|
+
"#{root}/dry/struct/{class_interface,errors,extensions,printer,value,version}.rb",
|
103
|
+
"#{root}/dry/struct/extensions"
|
104
|
+
)
|
105
|
+
end
|
106
|
+
end
|
96
107
|
end
|
97
108
|
|
98
|
-
|
109
|
+
loader.setup
|
99
110
|
|
100
111
|
include ::Dry::Equalizer(:__attributes__, inspect: false, immutable: true)
|
101
112
|
|
102
113
|
# {Dry::Types::Hash::Schema} subclass with specific behaviour defined for
|
103
114
|
# @return [Dry::Types::Hash::Schema]
|
104
115
|
defines :schema
|
105
|
-
schema Types[
|
116
|
+
schema Types["coercible.hash"].schema(EMPTY_HASH)
|
106
117
|
|
107
118
|
defines :abstract_class
|
108
119
|
abstract
|
@@ -134,7 +145,13 @@ module Dry
|
|
134
145
|
# rom_n_roda[:title] #=> 'Web Development with ROM and Roda'
|
135
146
|
# rom_n_roda[:subtitle] #=> nil
|
136
147
|
def [](name)
|
137
|
-
@attributes.fetch(name)
|
148
|
+
@attributes.fetch(name) do
|
149
|
+
if self.class.attribute_names.include?(name)
|
150
|
+
nil
|
151
|
+
else
|
152
|
+
raise MissingAttributeError.new(attribute: name, klass: self.class)
|
153
|
+
end
|
154
|
+
end
|
138
155
|
end
|
139
156
|
|
140
157
|
# Converts the {Dry::Struct} to a hash with keys representing
|
@@ -159,8 +176,8 @@ module Dry
|
|
159
176
|
result[key.name] = Hashify[self[key.name]] if attributes.key?(key.name)
|
160
177
|
end
|
161
178
|
end
|
179
|
+
# TODO: remove in 2.0
|
162
180
|
alias_method :to_hash, :to_h
|
163
|
-
# deprecate :to_hash, :to_h, message: "Implicit convertion structs to hashes is deprecated. Use .to_h"
|
164
181
|
|
165
182
|
# Create a copy of {Dry::Struct} with overriden attributes
|
166
183
|
#
|
@@ -183,10 +200,14 @@ module Dry
|
|
183
200
|
# rom_n_roda.new(subtitle: '3rd edition')
|
184
201
|
# #=> #<Book title="Web Development with ROM and Roda" subtitle="3rd edition">
|
185
202
|
def new(changeset)
|
186
|
-
new_attributes = self.class.schema.apply(
|
203
|
+
new_attributes = self.class.schema.apply(
|
204
|
+
changeset,
|
205
|
+
skip_missing: true,
|
206
|
+
resolve_defaults: false
|
207
|
+
)
|
187
208
|
self.class.load(__attributes__.merge(new_attributes))
|
188
|
-
rescue Types::SchemaError, Types::MissingKeyError, Types::UnknownKeysError =>
|
189
|
-
raise Error, "[#{self}.new] #{
|
209
|
+
rescue Types::SchemaError, Types::MissingKeyError, Types::UnknownKeysError => e
|
210
|
+
raise Error, "[#{self}.new] #{e}"
|
190
211
|
end
|
191
212
|
alias_method :__new__, :new
|
192
213
|
|
@@ -197,16 +218,13 @@ module Dry
|
|
197
218
|
"#<#{klass.name || klass.inspect}#{attrs}>"
|
198
219
|
end
|
199
220
|
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
def deconstruct_keys(keys)
|
205
|
-
attributes
|
206
|
-
end
|
207
|
-
end
|
221
|
+
# Pattern matching support
|
222
|
+
#
|
223
|
+
# @api private
|
224
|
+
def deconstruct_keys(_keys) = attributes
|
208
225
|
end
|
209
226
|
end
|
210
227
|
|
211
|
-
require
|
212
|
-
require
|
228
|
+
require "dry/struct/extensions"
|
229
|
+
require "dry/struct/printer"
|
230
|
+
require "dry/struct/value"
|
data/lib/dry-struct.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dry-struct
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Piotr Solnica
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-01-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dry-core
|
@@ -16,48 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
20
|
-
- - ">="
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
version: 0.4.4
|
23
|
-
type: :runtime
|
24
|
-
prerelease: false
|
25
|
-
version_requirements: !ruby/object:Gem::Requirement
|
26
|
-
requirements:
|
27
|
-
- - "~>"
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: '0.4'
|
30
|
-
- - ">="
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
version: 0.4.4
|
33
|
-
- !ruby/object:Gem::Dependency
|
34
|
-
name: dry-equalizer
|
35
|
-
requirement: !ruby/object:Gem::Requirement
|
36
|
-
requirements:
|
37
|
-
- - "~>"
|
38
|
-
- !ruby/object:Gem::Version
|
39
|
-
version: '0.3'
|
19
|
+
version: '1.1'
|
40
20
|
type: :runtime
|
41
21
|
prerelease: false
|
42
22
|
version_requirements: !ruby/object:Gem::Requirement
|
43
23
|
requirements:
|
44
24
|
- - "~>"
|
45
25
|
- !ruby/object:Gem::Version
|
46
|
-
version: '
|
26
|
+
version: '1.1'
|
47
27
|
- !ruby/object:Gem::Dependency
|
48
28
|
name: dry-types
|
49
29
|
requirement: !ruby/object:Gem::Requirement
|
50
30
|
requirements:
|
51
31
|
- - "~>"
|
52
32
|
- !ruby/object:Gem::Version
|
53
|
-
version: '1.
|
33
|
+
version: '1.8'
|
54
34
|
type: :runtime
|
55
35
|
prerelease: false
|
56
36
|
version_requirements: !ruby/object:Gem::Requirement
|
57
37
|
requirements:
|
58
38
|
- - "~>"
|
59
39
|
- !ruby/object:Gem::Version
|
60
|
-
version: '1.
|
40
|
+
version: '1.8'
|
61
41
|
- !ruby/object:Gem::Dependency
|
62
42
|
name: ice_nine
|
63
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -73,61 +53,19 @@ dependencies:
|
|
73
53
|
- !ruby/object:Gem::Version
|
74
54
|
version: '0.11'
|
75
55
|
- !ruby/object:Gem::Dependency
|
76
|
-
name:
|
77
|
-
requirement: !ruby/object:Gem::Requirement
|
78
|
-
requirements:
|
79
|
-
- - ">="
|
80
|
-
- !ruby/object:Gem::Version
|
81
|
-
version: '0'
|
82
|
-
type: :development
|
83
|
-
prerelease: false
|
84
|
-
version_requirements: !ruby/object:Gem::Requirement
|
85
|
-
requirements:
|
86
|
-
- - ">="
|
87
|
-
- !ruby/object:Gem::Version
|
88
|
-
version: '0'
|
89
|
-
- !ruby/object:Gem::Dependency
|
90
|
-
name: rake
|
91
|
-
requirement: !ruby/object:Gem::Requirement
|
92
|
-
requirements:
|
93
|
-
- - ">="
|
94
|
-
- !ruby/object:Gem::Version
|
95
|
-
version: '0'
|
96
|
-
type: :development
|
97
|
-
prerelease: false
|
98
|
-
version_requirements: !ruby/object:Gem::Requirement
|
99
|
-
requirements:
|
100
|
-
- - ">="
|
101
|
-
- !ruby/object:Gem::Version
|
102
|
-
version: '0'
|
103
|
-
- !ruby/object:Gem::Dependency
|
104
|
-
name: rspec
|
105
|
-
requirement: !ruby/object:Gem::Requirement
|
106
|
-
requirements:
|
107
|
-
- - ">="
|
108
|
-
- !ruby/object:Gem::Version
|
109
|
-
version: '0'
|
110
|
-
type: :development
|
111
|
-
prerelease: false
|
112
|
-
version_requirements: !ruby/object:Gem::Requirement
|
113
|
-
requirements:
|
114
|
-
- - ">="
|
115
|
-
- !ruby/object:Gem::Version
|
116
|
-
version: '0'
|
117
|
-
- !ruby/object:Gem::Dependency
|
118
|
-
name: yard
|
56
|
+
name: zeitwerk
|
119
57
|
requirement: !ruby/object:Gem::Requirement
|
120
58
|
requirements:
|
121
|
-
- - "
|
59
|
+
- - "~>"
|
122
60
|
- !ruby/object:Gem::Version
|
123
|
-
version: '
|
124
|
-
type: :
|
61
|
+
version: '2.6'
|
62
|
+
type: :runtime
|
125
63
|
prerelease: false
|
126
64
|
version_requirements: !ruby/object:Gem::Requirement
|
127
65
|
requirements:
|
128
|
-
- - "
|
66
|
+
- - "~>"
|
129
67
|
- !ruby/object:Gem::Version
|
130
|
-
version: '
|
68
|
+
version: '2.6'
|
131
69
|
description: Typed structs and value objects
|
132
70
|
email:
|
133
71
|
- piotr.solnica@gmail.com
|
@@ -158,10 +96,11 @@ licenses:
|
|
158
96
|
- MIT
|
159
97
|
metadata:
|
160
98
|
allowed_push_host: https://rubygems.org
|
161
|
-
changelog_uri: https://github.com/dry-rb/dry-struct/blob/
|
99
|
+
changelog_uri: https://github.com/dry-rb/dry-struct/blob/main/CHANGELOG.md
|
162
100
|
source_code_uri: https://github.com/dry-rb/dry-struct
|
163
101
|
bug_tracker_uri: https://github.com/dry-rb/dry-struct/issues
|
164
|
-
|
102
|
+
rubygems_mfa_required: 'true'
|
103
|
+
post_install_message:
|
165
104
|
rdoc_options: []
|
166
105
|
require_paths:
|
167
106
|
- lib
|
@@ -169,15 +108,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
169
108
|
requirements:
|
170
109
|
- - ">="
|
171
110
|
- !ruby/object:Gem::Version
|
172
|
-
version:
|
111
|
+
version: 3.1.0
|
173
112
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
174
113
|
requirements:
|
175
114
|
- - ">="
|
176
115
|
- !ruby/object:Gem::Version
|
177
116
|
version: '0'
|
178
117
|
requirements: []
|
179
|
-
rubygems_version: 3.
|
180
|
-
signing_key:
|
118
|
+
rubygems_version: 3.3.27
|
119
|
+
signing_key:
|
181
120
|
specification_version: 4
|
182
121
|
summary: Typed structs and value objects
|
183
122
|
test_files: []
|