dry-struct 1.3.0 → 1.6.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 +85 -5
- data/LICENSE +1 -1
- data/README.md +5 -4
- data/dry-struct.gemspec +17 -16
- data/lib/dry/struct/class_interface.rb +32 -33
- data/lib/dry/struct/compiler.rb +0 -3
- data/lib/dry/struct/errors.rb +1 -1
- data/lib/dry/struct/extensions/pretty_print.rb +6 -6
- data/lib/dry/struct/extensions.rb +1 -1
- data/lib/dry/struct/printer.rb +1 -1
- data/lib/dry/struct/struct_builder.rb +22 -8
- data/lib/dry/struct/sum.rb +3 -6
- data/lib/dry/struct/value.rb +2 -3
- data/lib/dry/struct/version.rb +1 -1
- data/lib/dry/struct.rb +42 -28
- data/lib/dry-struct.rb +1 -1
- metadata +28 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f3309e15a4b8084a8ddb210a4d62e51e063a54f0aec56f41398f41824bbfe687
|
4
|
+
data.tar.gz: 05de1a1085a1753cd22f6f42a459de2245a544fe6ab822dff2bae228fe91da45
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 16f8476d1362fa11871db6be02787e8b106795ca5d4a1ebeb1c796cc22abcd5ee0c0cf8f7985191a180dcfb38a1679535be4ff13003e0b08459072a2b236e288
|
7
|
+
data.tar.gz: e8973dbc9cc1fc0033751299ac366504c047cd996e9e9c5718ecad6e2d4bf2cdb734d46fd76f99c074a7982cb8cff6f9085a18725a01b21ea6e42475218f06e5
|
data/CHANGELOG.md
CHANGED
@@ -1,9 +1,70 @@
|
|
1
|
+
<!--- DO NOT EDIT THIS FILE - IT'S AUTOMATICALLY GENERATED VIA DEVTOOLS --->
|
2
|
+
|
3
|
+
## 1.6.0 2022-11-04
|
4
|
+
|
5
|
+
|
6
|
+
### Changed
|
7
|
+
|
8
|
+
- This version uses dry-core 1.0 (@flash-gordon + @solnic)
|
9
|
+
|
10
|
+
[Compare v1.5.2...v1.6.0](https://github.com/dry-rb/dry-struct/compare/v1.5.2...v1.6.0)
|
11
|
+
|
12
|
+
## 1.5.2 2022-10-19
|
13
|
+
|
14
|
+
|
15
|
+
### Fixed
|
16
|
+
|
17
|
+
- Coercion failures keep the original error instead of just having a string (@flash-gordon + @newx)
|
18
|
+
|
19
|
+
|
20
|
+
[Compare v1.5.1...v1.5.2](https://github.com/dry-rb/dry-struct/compare/v1.5.1...v1.5.2)
|
21
|
+
|
22
|
+
## 1.5.1 2022-10-17
|
23
|
+
|
24
|
+
|
25
|
+
### Fixed
|
26
|
+
|
27
|
+
- Fixed issues with auto-loading `Extensions` module (issue #183 fixed via #184) (@solnic)
|
28
|
+
|
29
|
+
|
30
|
+
[Compare v1.5.0...v1.5.1](https://github.com/dry-rb/dry-struct/compare/v1.5.0...v1.5.1)
|
31
|
+
|
32
|
+
## 1.5.0 2022-10-15
|
33
|
+
|
34
|
+
|
35
|
+
### Changed
|
36
|
+
|
37
|
+
- Use zeitwerk for auto-loading (@flash-gordon)
|
38
|
+
|
39
|
+
[Compare v1.4.0...v1.5.0](https://github.com/dry-rb/dry-struct/compare/v1.4.0...v1.5.0)
|
40
|
+
|
41
|
+
## 1.4.0 2021-01-21
|
42
|
+
|
43
|
+
|
44
|
+
### Added
|
45
|
+
|
46
|
+
- Support for wrapping constructors and fallbacks, see release notes for dry-types 1.5.0 (@flash-gordon)
|
47
|
+
- Improvements of the attribute DSL, now it's possible to use optional structs as a base class (@flash-gordon)
|
48
|
+
```ruby
|
49
|
+
class User < Dry::Struct
|
50
|
+
attribute :name, Types::String
|
51
|
+
attribute :address, Dry::Struct.optional do
|
52
|
+
attribute :city, Types::String
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
User.new(name: "John", address: nil) # => #<User name="John" address=nil>
|
57
|
+
```
|
58
|
+
|
59
|
+
|
60
|
+
[Compare v1.3.0...v1.4.0](https://github.com/dry-rb/dry-struct/compare/v1.3.0...v1.4.0)
|
61
|
+
|
1
62
|
## 1.3.0 2020-02-10
|
2
63
|
|
3
64
|
|
4
65
|
### Added
|
5
66
|
|
6
|
-
- Nested structures will reuse type and key transformations from
|
67
|
+
- Nested structures will reuse type and key transformations from the enclosing struct (@flash-gordon)
|
7
68
|
|
8
69
|
```ruby
|
9
70
|
class User < Dry::Struct
|
@@ -22,13 +83,32 @@
|
|
22
83
|
end
|
23
84
|
end
|
24
85
|
```
|
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)
|
86
|
+
- `Dry::Struct::Constructor` finally acts like a fully-featured type (@flash-gordon)
|
87
|
+
- `Dry::Struct.abstract` declares a struct class as abstract. An abstract class is used as a default superclass for nested structs (@flash-gordon)
|
88
|
+
- `Dry::Struct.to_ast` and struct compiler (@flash-gordon)
|
89
|
+
- Struct composition with `Dry::Struct.attributes_from`. It's more flexible than inheritance (@waiting-for-dev + @flash-gordon)
|
90
|
+
|
91
|
+
```ruby
|
92
|
+
class Address < Dry::Struct
|
93
|
+
attribute :city, Types::String
|
94
|
+
attribute :zipcode, Types::String
|
95
|
+
end
|
96
|
+
|
97
|
+
class Buyer < Dry::Struct
|
98
|
+
attribute :name, Types::String
|
99
|
+
attributes_from Address
|
100
|
+
end
|
101
|
+
|
102
|
+
class Seller < Dry::Struct
|
103
|
+
attribute :name, Types::String
|
104
|
+
attribute :email, Types::String
|
105
|
+
attributes_from Address
|
106
|
+
end
|
107
|
+
```
|
28
108
|
|
29
109
|
### Changed
|
30
110
|
|
31
|
-
- [internal] metadata is now stored inside schema (flash-gordon)
|
111
|
+
- [internal] metadata is now stored inside schema (@flash-gordon)
|
32
112
|
|
33
113
|
[Compare v1.2.0...v1.3.0](https://github.com/dry-rb/dry-struct/compare/v1.2.0...v1.3.0)
|
34
114
|
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -1,3 +1,4 @@
|
|
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
4
|
[codacy]: https://www.codacy.com/gh/dry-rb/dry-struct
|
@@ -10,19 +11,19 @@
|
|
10
11
|
[][actions]
|
11
12
|
[][codacy]
|
12
13
|
[][codacy]
|
13
|
-
[][inchpages]
|
14
15
|
|
15
16
|
## Links
|
16
17
|
|
17
|
-
* [User documentation](
|
18
|
+
* [User documentation](https://dry-rb.org/gems/dry-struct)
|
18
19
|
* [API documentation](http://rubydoc.info/gems/dry-struct)
|
19
20
|
|
20
21
|
## Supported Ruby versions
|
21
22
|
|
22
23
|
This library officially supports the following Ruby versions:
|
23
24
|
|
24
|
-
* MRI
|
25
|
-
* jruby
|
25
|
+
* MRI `>= 2.7.0`
|
26
|
+
* jruby `>= 9.3` (postponed until 2.7 is supported)
|
26
27
|
|
27
28
|
## License
|
28
29
|
|
data/dry-struct.gemspec
CHANGED
@@ -1,37 +1,38 @@
|
|
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"
|
27
28
|
|
28
|
-
spec.required_ruby_version = ">= 2.
|
29
|
+
spec.required_ruby_version = ">= 2.7.0"
|
29
30
|
|
30
31
|
# to update dependencies edit project.yml
|
31
|
-
spec.add_runtime_dependency "dry-core", "~> 0
|
32
|
-
spec.add_runtime_dependency "dry-
|
33
|
-
spec.add_runtime_dependency "dry-types", "~> 1.3"
|
32
|
+
spec.add_runtime_dependency "dry-core", "~> 1.0", "< 2"
|
33
|
+
spec.add_runtime_dependency "dry-types", ">= 1.7", "< 2"
|
34
34
|
spec.add_runtime_dependency "ice_nine", "~> 0.11"
|
35
|
+
spec.add_runtime_dependency "zeitwerk", "~> 2.6"
|
35
36
|
|
36
37
|
spec.add_development_dependency "bundler"
|
37
38
|
spec.add_development_dependency "rake"
|
@@ -1,18 +1,11 @@
|
|
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
|
@@ -22,7 +15,7 @@ module Dry
|
|
22
15
|
def inherited(klass)
|
23
16
|
super
|
24
17
|
|
25
|
-
unless klass.name.eql?(
|
18
|
+
unless klass.name.eql?("Dry::Struct::Value")
|
26
19
|
klass.extend(Core::DescendantsTracker)
|
27
20
|
end
|
28
21
|
end
|
@@ -49,8 +42,12 @@ module Dry
|
|
49
42
|
# end
|
50
43
|
# end
|
51
44
|
#
|
52
|
-
# Language.schema
|
53
|
-
# # => #<Dry::Types[
|
45
|
+
# Language.schema # new lines for readability
|
46
|
+
# # => #<Dry::Types[
|
47
|
+
# Constructor<Schema<keys={
|
48
|
+
# name: Constrained<Nominal<String> rule=[type?(String)]>
|
49
|
+
# details: Language::Details
|
50
|
+
# }> fn=Kernel.Hash>]>
|
54
51
|
#
|
55
52
|
# ruby = Language.new(name: 'Ruby', details: { type: 'OO' })
|
56
53
|
# ruby.name #=> 'Ruby'
|
@@ -67,10 +64,12 @@ module Dry
|
|
67
64
|
# end
|
68
65
|
# end
|
69
66
|
#
|
70
|
-
# Language.schema
|
67
|
+
# Language.schema # new lines for readability
|
71
68
|
# => #<Dry::Types[Constructor<Schema<keys={
|
72
69
|
# name: Constrained<Nominal<String> rule=[type?(String)]>
|
73
|
-
# versions: Constrained<
|
70
|
+
# versions: Constrained<
|
71
|
+
# Array<Constrained<Nominal<String> rule=[type?(String)]>
|
72
|
+
# > rule=[type?(Array)]>
|
74
73
|
# celebrities: Constrained<Array<Language::Celebrity> rule=[type?(Array)]>
|
75
74
|
# }> fn=Kernel.Hash>]>
|
76
75
|
#
|
@@ -149,9 +148,9 @@ module Dry
|
|
149
148
|
def attribute?(*args, &block)
|
150
149
|
if args.size == 1 && block.nil?
|
151
150
|
Core::Deprecations.warn(
|
152
|
-
|
153
|
-
|
154
|
-
tag: :
|
151
|
+
"Dry::Struct.attribute? is deprecated for checking attribute presence, "\
|
152
|
+
"use has_attribute? instead",
|
153
|
+
tag: :"dry-struct"
|
155
154
|
)
|
156
155
|
|
157
156
|
has_attribute?(args[0])
|
@@ -181,7 +180,7 @@ module Dry
|
|
181
180
|
# # author: Constrained<Nominal<String> rule=[type?(String)]>
|
182
181
|
# # }> fn=Kernel.Hash>]>
|
183
182
|
def attributes(new_schema)
|
184
|
-
keys = new_schema.keys.map { |k| k.to_s.chomp(
|
183
|
+
keys = new_schema.keys.map { |k| k.to_s.chomp("?").to_sym }
|
185
184
|
check_schema_duplication(keys)
|
186
185
|
|
187
186
|
schema schema.schema(new_schema)
|
@@ -192,7 +191,7 @@ module Dry
|
|
192
191
|
|
193
192
|
direct_descendants = descendants.select { |d| d.superclass == self }
|
194
193
|
direct_descendants.each do |d|
|
195
|
-
inherited_attrs = new_schema.reject { |k, _| d.has_attribute?(k.to_s.chomp(
|
194
|
+
inherited_attrs = new_schema.reject { |k, _| d.has_attribute?(k.to_s.chomp("?").to_sym) }
|
196
195
|
d.attributes(inherited_attrs)
|
197
196
|
end
|
198
197
|
|
@@ -233,7 +232,7 @@ module Dry
|
|
233
232
|
schema schema.with_key_transform(proc || block)
|
234
233
|
end
|
235
234
|
|
236
|
-
# @param [Hash{Symbol => Dry::Types::Type, Dry::Struct}]
|
235
|
+
# @param [Hash{Symbol => Dry::Types::Type, Dry::Struct}] new_keys
|
237
236
|
# @raise [RepeatedAttributeError] when trying to define attribute with the
|
238
237
|
# same name as previously defined one
|
239
238
|
def check_schema_duplication(new_keys)
|
@@ -247,7 +246,7 @@ module Dry
|
|
247
246
|
|
248
247
|
# @param [Hash{Symbol => Object},Dry::Struct] attributes
|
249
248
|
# @raise [Struct::Error] if the given attributes don't conform {#schema}
|
250
|
-
def new(attributes = default_attributes, safe = false, &block)
|
249
|
+
def new(attributes = default_attributes, safe = false, &block) # rubocop:disable Style/OptionalBooleanParameter
|
251
250
|
if attributes.is_a?(Struct)
|
252
251
|
if equal?(attributes.class)
|
253
252
|
attributes
|
@@ -264,8 +263,8 @@ module Dry
|
|
264
263
|
else
|
265
264
|
load(schema.call_unsafe(attributes))
|
266
265
|
end
|
267
|
-
rescue Types::CoercionError =>
|
268
|
-
raise Error, "[#{self}.new] #{
|
266
|
+
rescue Types::CoercionError => e
|
267
|
+
raise Error, "[#{self}.new] #{e}", e.backtrace
|
269
268
|
end
|
270
269
|
|
271
270
|
# @api private
|
@@ -289,7 +288,7 @@ module Dry
|
|
289
288
|
# @api private
|
290
289
|
def load(attributes)
|
291
290
|
struct = allocate
|
292
|
-
struct.
|
291
|
+
struct.__send__(:initialize, attributes)
|
293
292
|
struct
|
294
293
|
end
|
295
294
|
|
@@ -297,17 +296,17 @@ module Dry
|
|
297
296
|
# @param [#call,nil] block
|
298
297
|
# @return [Dry::Struct::Constructor]
|
299
298
|
def constructor(constructor = nil, **, &block)
|
300
|
-
Constructor
|
299
|
+
Constructor[self, fn: constructor || block]
|
301
300
|
end
|
302
301
|
|
303
302
|
# @param [Hash{Symbol => Object},Dry::Struct] input
|
304
303
|
# @yieldparam [Dry::Types::Result::Failure] failure
|
305
|
-
# @yieldreturn [Dry::Types::
|
304
|
+
# @yieldreturn [Dry::Types::Result]
|
306
305
|
# @return [Dry::Types::Result]
|
307
306
|
def try(input)
|
308
307
|
success(self[input])
|
309
308
|
rescue Error => e
|
310
|
-
failure_result = failure(input, e
|
309
|
+
failure_result = failure(input, e)
|
311
310
|
block_given? ? yield(failure_result) : failure_result
|
312
311
|
end
|
313
312
|
|
@@ -345,7 +344,7 @@ module Dry
|
|
345
344
|
false
|
346
345
|
end
|
347
346
|
|
348
|
-
# @param [Object, Dry::Struct]
|
347
|
+
# @param [Object, Dry::Struct] other
|
349
348
|
# @return [Boolean]
|
350
349
|
def ===(other)
|
351
350
|
other.is_a?(self)
|
@@ -463,7 +462,7 @@ module Dry
|
|
463
462
|
elsif block.nil? && Undefined.equal?(type)
|
464
463
|
raise(
|
465
464
|
::ArgumentError,
|
466
|
-
|
465
|
+
"you must supply a type or a block to `Dry::Struct.attribute`"
|
467
466
|
)
|
468
467
|
else
|
469
468
|
type
|
@@ -481,10 +480,10 @@ module Dry
|
|
481
480
|
keys.each do |key|
|
482
481
|
next if instance_methods.include?(key)
|
483
482
|
|
484
|
-
class_eval(<<-RUBY)
|
485
|
-
def #{key}
|
486
|
-
@attributes[#{key.inspect}]
|
487
|
-
end
|
483
|
+
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
484
|
+
def #{key} # def email
|
485
|
+
@attributes[#{key.inspect}] # @attributes[:email]
|
486
|
+
end # end
|
488
487
|
RUBY
|
489
488
|
end
|
490
489
|
end
|
data/lib/dry/struct/compiler.rb
CHANGED
data/lib/dry/struct/errors.rb
CHANGED
@@ -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/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,7 +12,8 @@ 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
18
|
def call(attr_name, type, &block)
|
20
19
|
const_name = const_name(type, attr_name)
|
@@ -30,10 +29,13 @@ module Dry
|
|
30
29
|
|
31
30
|
class_exec(&block)
|
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,23 @@ module Dry
|
|
41
43
|
|
42
44
|
private
|
43
45
|
|
46
|
+
def type?(type)
|
47
|
+
type.is_a?(Types::Type)
|
48
|
+
end
|
49
|
+
|
44
50
|
def array?(type)
|
45
|
-
type
|
51
|
+
type?(type) && !type.optional? && type.primitive.equal?(::Array)
|
52
|
+
end
|
53
|
+
|
54
|
+
def optional?(type)
|
55
|
+
type?(type) && type.optional?
|
46
56
|
end
|
47
57
|
|
48
58
|
def parent(type)
|
49
59
|
if array?(type)
|
50
60
|
visit(type.to_ast)
|
61
|
+
elsif optional?(type)
|
62
|
+
type.right
|
51
63
|
else
|
52
64
|
type
|
53
65
|
end
|
@@ -65,10 +77,12 @@ module Dry
|
|
65
77
|
end
|
66
78
|
|
67
79
|
def check_name(name)
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
80
|
+
if struct.const_defined?(name, false)
|
81
|
+
raise(
|
82
|
+
Error,
|
83
|
+
"Can't create nested attribute - `#{struct}::#{name}` already defined"
|
84
|
+
)
|
85
|
+
end
|
72
86
|
end
|
73
87
|
|
74
88
|
def visit_constrained(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,7 +14,7 @@ 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)
|
@@ -46,9 +43,9 @@ module Dry
|
|
46
43
|
protected
|
47
44
|
|
48
45
|
# @private
|
49
|
-
def try_struct(input)
|
46
|
+
def try_struct(input, &block)
|
50
47
|
left.try_struct(input) do
|
51
|
-
right.try_struct(input)
|
48
|
+
right.try_struct(input, &block)
|
52
49
|
end
|
53
50
|
end
|
54
51
|
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)
|
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}.
|
@@ -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,7 @@ 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) { raise MissingAttributeError
|
148
|
+
@attributes.fetch(name) { raise MissingAttributeError, name }
|
138
149
|
end
|
139
150
|
|
140
151
|
# Converts the {Dry::Struct} to a hash with keys representing
|
@@ -159,8 +170,8 @@ module Dry
|
|
159
170
|
result[key.name] = Hashify[self[key.name]] if attributes.key?(key.name)
|
160
171
|
end
|
161
172
|
end
|
173
|
+
# TODO: remove in 2.0
|
162
174
|
alias_method :to_hash, :to_h
|
163
|
-
# deprecate :to_hash, :to_h, message: "Implicit convertion structs to hashes is deprecated. Use .to_h"
|
164
175
|
|
165
176
|
# Create a copy of {Dry::Struct} with overriden attributes
|
166
177
|
#
|
@@ -183,10 +194,14 @@ module Dry
|
|
183
194
|
# rom_n_roda.new(subtitle: '3rd edition')
|
184
195
|
# #=> #<Book title="Web Development with ROM and Roda" subtitle="3rd edition">
|
185
196
|
def new(changeset)
|
186
|
-
new_attributes = self.class.schema.apply(
|
197
|
+
new_attributes = self.class.schema.apply(
|
198
|
+
changeset,
|
199
|
+
skip_missing: true,
|
200
|
+
resolve_defaults: false
|
201
|
+
)
|
187
202
|
self.class.load(__attributes__.merge(new_attributes))
|
188
|
-
rescue Types::SchemaError, Types::MissingKeyError, Types::UnknownKeysError =>
|
189
|
-
raise Error, "[#{self}.new] #{
|
203
|
+
rescue Types::SchemaError, Types::MissingKeyError, Types::UnknownKeysError => e
|
204
|
+
raise Error, "[#{self}.new] #{e}"
|
190
205
|
end
|
191
206
|
alias_method :__new__, :new
|
192
207
|
|
@@ -197,16 +212,15 @@ module Dry
|
|
197
212
|
"#<#{klass.name || klass.inspect}#{attrs}>"
|
198
213
|
end
|
199
214
|
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
attributes
|
206
|
-
end
|
215
|
+
# Pattern matching support
|
216
|
+
#
|
217
|
+
# @api private
|
218
|
+
def deconstruct_keys(_keys)
|
219
|
+
attributes
|
207
220
|
end
|
208
221
|
end
|
209
222
|
end
|
210
223
|
|
211
|
-
require
|
212
|
-
require
|
224
|
+
require "dry/struct/extensions"
|
225
|
+
require "dry/struct/printer"
|
226
|
+
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.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Piotr Solnica
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-11-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dry-core
|
@@ -16,62 +16,68 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '0
|
20
|
-
- - "
|
19
|
+
version: '1.0'
|
20
|
+
- - "<"
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version:
|
22
|
+
version: '2'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
27
|
- - "~>"
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: '0
|
30
|
-
- - "
|
29
|
+
version: '1.0'
|
30
|
+
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version:
|
32
|
+
version: '2'
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
|
-
name: dry-
|
34
|
+
name: dry-types
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
36
36
|
requirements:
|
37
|
-
- - "
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '1.7'
|
40
|
+
- - "<"
|
38
41
|
- !ruby/object:Gem::Version
|
39
|
-
version: '
|
42
|
+
version: '2'
|
40
43
|
type: :runtime
|
41
44
|
prerelease: false
|
42
45
|
version_requirements: !ruby/object:Gem::Requirement
|
43
46
|
requirements:
|
44
|
-
- - "
|
47
|
+
- - ">="
|
45
48
|
- !ruby/object:Gem::Version
|
46
|
-
version: '
|
49
|
+
version: '1.7'
|
50
|
+
- - "<"
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '2'
|
47
53
|
- !ruby/object:Gem::Dependency
|
48
|
-
name:
|
54
|
+
name: ice_nine
|
49
55
|
requirement: !ruby/object:Gem::Requirement
|
50
56
|
requirements:
|
51
57
|
- - "~>"
|
52
58
|
- !ruby/object:Gem::Version
|
53
|
-
version: '
|
59
|
+
version: '0.11'
|
54
60
|
type: :runtime
|
55
61
|
prerelease: false
|
56
62
|
version_requirements: !ruby/object:Gem::Requirement
|
57
63
|
requirements:
|
58
64
|
- - "~>"
|
59
65
|
- !ruby/object:Gem::Version
|
60
|
-
version: '
|
66
|
+
version: '0.11'
|
61
67
|
- !ruby/object:Gem::Dependency
|
62
|
-
name:
|
68
|
+
name: zeitwerk
|
63
69
|
requirement: !ruby/object:Gem::Requirement
|
64
70
|
requirements:
|
65
71
|
- - "~>"
|
66
72
|
- !ruby/object:Gem::Version
|
67
|
-
version: '
|
73
|
+
version: '2.6'
|
68
74
|
type: :runtime
|
69
75
|
prerelease: false
|
70
76
|
version_requirements: !ruby/object:Gem::Requirement
|
71
77
|
requirements:
|
72
78
|
- - "~>"
|
73
79
|
- !ruby/object:Gem::Version
|
74
|
-
version: '
|
80
|
+
version: '2.6'
|
75
81
|
- !ruby/object:Gem::Dependency
|
76
82
|
name: bundler
|
77
83
|
requirement: !ruby/object:Gem::Requirement
|
@@ -158,7 +164,7 @@ licenses:
|
|
158
164
|
- MIT
|
159
165
|
metadata:
|
160
166
|
allowed_push_host: https://rubygems.org
|
161
|
-
changelog_uri: https://github.com/dry-rb/dry-struct/blob/
|
167
|
+
changelog_uri: https://github.com/dry-rb/dry-struct/blob/main/CHANGELOG.md
|
162
168
|
source_code_uri: https://github.com/dry-rb/dry-struct
|
163
169
|
bug_tracker_uri: https://github.com/dry-rb/dry-struct/issues
|
164
170
|
post_install_message:
|
@@ -169,14 +175,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
169
175
|
requirements:
|
170
176
|
- - ">="
|
171
177
|
- !ruby/object:Gem::Version
|
172
|
-
version: 2.
|
178
|
+
version: 2.7.0
|
173
179
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
174
180
|
requirements:
|
175
181
|
- - ">="
|
176
182
|
- !ruby/object:Gem::Version
|
177
183
|
version: '0'
|
178
184
|
requirements: []
|
179
|
-
rubygems_version: 3.
|
185
|
+
rubygems_version: 3.1.6
|
180
186
|
signing_key:
|
181
187
|
specification_version: 4
|
182
188
|
summary: Typed structs and value objects
|