dry-struct 1.3.0 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![CI Status](https://github.com/dry-rb/dry-struct/workflows/ci/badge.svg)][actions]
|
11
12
|
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/961f5c776f1d49218b2cede3745e059c)][codacy]
|
12
13
|
[![Codacy Badge](https://api.codacy.com/project/badge/Coverage/961f5c776f1d49218b2cede3745e059c)][codacy]
|
13
|
-
[![Inline docs](http://inch-ci.org/github/dry-rb/dry-struct.svg?branch=
|
14
|
+
[![Inline docs](http://inch-ci.org/github/dry-rb/dry-struct.svg?branch=main)][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
|