dry-struct 1.3.0 → 1.5.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 +56 -5
- data/LICENSE +1 -1
- data/README.md +5 -4
- data/dry-struct.gemspec +17 -16
- data/lib/dry/struct/class_interface.rb +30 -31
- 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 +2 -5
- data/lib/dry/struct/value.rb +2 -3
- data/lib/dry/struct/version.rb +1 -1
- data/lib/dry/struct.rb +41 -28
- data/lib/dry-struct.rb +1 -1
- metadata +18 -18
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b4e5c0ce0e83f1e4c7308d2d6ee56ac5397d3960a455e2c0818036a67fe5d63a
|
|
4
|
+
data.tar.gz: 77add215b7f8f7f84b9a4e70a76cdfa03fa0ddf63f51ae549652398bb8ec0b84
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 00b42458408d8bd72847b19a0564ae1909ff9d88235d2a8a1769638bda63f088429464983fd108b532af09d61583e6500566f6ea9391eda84b6c937d0844cff9
|
|
7
|
+
data.tar.gz: ed436e9e01d782dd717d0a67ae98813c0398631d10a81e367355eaae9e870c7580f2c840644577ee2ad8fa651264dd0c5d437a896a2d906b038d2659de54195e
|
data/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,41 @@
|
|
|
1
|
+
<!--- DO NOT EDIT THIS FILE - IT'S AUTOMATICALLY GENERATED VIA DEVTOOLS --->
|
|
2
|
+
|
|
3
|
+
## 1.5.0 2022-10-15
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Changed
|
|
7
|
+
|
|
8
|
+
- Use zeitwerk for auto-loading (@flash-gordon)
|
|
9
|
+
|
|
10
|
+
[Compare v1.4.0...v1.5.0](https://github.com/dry-rb/dry-struct/compare/v1.4.0...v1.5.0)
|
|
11
|
+
|
|
12
|
+
## 1.4.0 2021-01-21
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- Support for wrapping constructors and fallbacks, see release notes for dry-types 1.5.0 (@flash-gordon)
|
|
18
|
+
- Improvements of the attribute DSL, now it's possible to use optional structs as a base class (@flash-gordon)
|
|
19
|
+
```ruby
|
|
20
|
+
class User < Dry::Struct
|
|
21
|
+
attribute :name, Types::String
|
|
22
|
+
attribute :address, Dry::Struct.optional do
|
|
23
|
+
attribute :city, Types::String
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
User.new(name: "John", address: nil) # => #<User name="John" address=nil>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
[Compare v1.3.0...v1.4.0](https://github.com/dry-rb/dry-struct/compare/v1.3.0...v1.4.0)
|
|
32
|
+
|
|
1
33
|
## 1.3.0 2020-02-10
|
|
2
34
|
|
|
3
35
|
|
|
4
36
|
### Added
|
|
5
37
|
|
|
6
|
-
- Nested structures will reuse type and key transformations from
|
|
38
|
+
- Nested structures will reuse type and key transformations from the enclosing struct (@flash-gordon)
|
|
7
39
|
|
|
8
40
|
```ruby
|
|
9
41
|
class User < Dry::Struct
|
|
@@ -22,13 +54,32 @@
|
|
|
22
54
|
end
|
|
23
55
|
end
|
|
24
56
|
```
|
|
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)
|
|
57
|
+
- `Dry::Struct::Constructor` finally acts like a fully-featured type (@flash-gordon)
|
|
58
|
+
- `Dry::Struct.abstract` declares a struct class as abstract. An abstract class is used as a default superclass for nested structs (@flash-gordon)
|
|
59
|
+
- `Dry::Struct.to_ast` and struct compiler (@flash-gordon)
|
|
60
|
+
- Struct composition with `Dry::Struct.attributes_from`. It's more flexible than inheritance (@waiting-for-dev + @flash-gordon)
|
|
61
|
+
|
|
62
|
+
```ruby
|
|
63
|
+
class Address < Dry::Struct
|
|
64
|
+
attribute :city, Types::String
|
|
65
|
+
attribute :zipcode, Types::String
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
class Buyer < Dry::Struct
|
|
69
|
+
attribute :name, Types::String
|
|
70
|
+
attributes_from Address
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
class Seller < Dry::Struct
|
|
74
|
+
attribute :name, Types::String
|
|
75
|
+
attribute :email, Types::String
|
|
76
|
+
attributes_from Address
|
|
77
|
+
end
|
|
78
|
+
```
|
|
28
79
|
|
|
29
80
|
### Changed
|
|
30
81
|
|
|
31
|
-
- [internal] metadata is now stored inside schema (flash-gordon)
|
|
82
|
+
- [internal] metadata is now stored inside schema (@flash-gordon)
|
|
32
83
|
|
|
33
84
|
[Compare v1.2.0...v1.3.0](https://github.com/dry-rb/dry-struct/compare/v1.2.0...v1.3.0)
|
|
34
85
|
|
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", "~> 0.9", ">= 0.9"
|
|
33
|
+
spec.add_runtime_dependency "dry-types", "~> 1.6"
|
|
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,7 +296,7 @@ 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
|
|
@@ -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
|
|
@@ -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,34 @@ 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
|
+
)
|
|
104
|
+
end
|
|
105
|
+
end
|
|
96
106
|
end
|
|
97
107
|
|
|
98
|
-
|
|
108
|
+
loader.setup
|
|
99
109
|
|
|
100
110
|
include ::Dry::Equalizer(:__attributes__, inspect: false, immutable: true)
|
|
101
111
|
|
|
102
112
|
# {Dry::Types::Hash::Schema} subclass with specific behaviour defined for
|
|
103
113
|
# @return [Dry::Types::Hash::Schema]
|
|
104
114
|
defines :schema
|
|
105
|
-
schema Types[
|
|
115
|
+
schema Types["coercible.hash"].schema(EMPTY_HASH)
|
|
106
116
|
|
|
107
117
|
defines :abstract_class
|
|
108
118
|
abstract
|
|
@@ -134,7 +144,7 @@ module Dry
|
|
|
134
144
|
# rom_n_roda[:title] #=> 'Web Development with ROM and Roda'
|
|
135
145
|
# rom_n_roda[:subtitle] #=> nil
|
|
136
146
|
def [](name)
|
|
137
|
-
@attributes.fetch(name) { raise MissingAttributeError
|
|
147
|
+
@attributes.fetch(name) { raise MissingAttributeError, name }
|
|
138
148
|
end
|
|
139
149
|
|
|
140
150
|
# Converts the {Dry::Struct} to a hash with keys representing
|
|
@@ -159,8 +169,8 @@ module Dry
|
|
|
159
169
|
result[key.name] = Hashify[self[key.name]] if attributes.key?(key.name)
|
|
160
170
|
end
|
|
161
171
|
end
|
|
172
|
+
# TODO: remove in 2.0
|
|
162
173
|
alias_method :to_hash, :to_h
|
|
163
|
-
# deprecate :to_hash, :to_h, message: "Implicit convertion structs to hashes is deprecated. Use .to_h"
|
|
164
174
|
|
|
165
175
|
# Create a copy of {Dry::Struct} with overriden attributes
|
|
166
176
|
#
|
|
@@ -183,10 +193,14 @@ module Dry
|
|
|
183
193
|
# rom_n_roda.new(subtitle: '3rd edition')
|
|
184
194
|
# #=> #<Book title="Web Development with ROM and Roda" subtitle="3rd edition">
|
|
185
195
|
def new(changeset)
|
|
186
|
-
new_attributes = self.class.schema.apply(
|
|
196
|
+
new_attributes = self.class.schema.apply(
|
|
197
|
+
changeset,
|
|
198
|
+
skip_missing: true,
|
|
199
|
+
resolve_defaults: false
|
|
200
|
+
)
|
|
187
201
|
self.class.load(__attributes__.merge(new_attributes))
|
|
188
|
-
rescue Types::SchemaError, Types::MissingKeyError, Types::UnknownKeysError =>
|
|
189
|
-
raise Error, "[#{self}.new] #{
|
|
202
|
+
rescue Types::SchemaError, Types::MissingKeyError, Types::UnknownKeysError => e
|
|
203
|
+
raise Error, "[#{self}.new] #{e}"
|
|
190
204
|
end
|
|
191
205
|
alias_method :__new__, :new
|
|
192
206
|
|
|
@@ -197,16 +211,15 @@ module Dry
|
|
|
197
211
|
"#<#{klass.name || klass.inspect}#{attrs}>"
|
|
198
212
|
end
|
|
199
213
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
attributes
|
|
206
|
-
end
|
|
214
|
+
# Pattern matching support
|
|
215
|
+
#
|
|
216
|
+
# @api private
|
|
217
|
+
def deconstruct_keys(_keys)
|
|
218
|
+
attributes
|
|
207
219
|
end
|
|
208
220
|
end
|
|
209
221
|
end
|
|
210
222
|
|
|
211
|
-
require
|
|
212
|
-
require
|
|
223
|
+
require "dry/struct/extensions"
|
|
224
|
+
require "dry/struct/printer"
|
|
225
|
+
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.5.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-10-15 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: dry-core
|
|
@@ -16,62 +16,62 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '0.
|
|
19
|
+
version: '0.9'
|
|
20
20
|
- - ">="
|
|
21
21
|
- !ruby/object:Gem::Version
|
|
22
|
-
version: 0.
|
|
22
|
+
version: '0.9'
|
|
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.
|
|
29
|
+
version: '0.9'
|
|
30
30
|
- - ">="
|
|
31
31
|
- !ruby/object:Gem::Version
|
|
32
|
-
version: 0.
|
|
32
|
+
version: '0.9'
|
|
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
38
|
- !ruby/object:Gem::Version
|
|
39
|
-
version: '
|
|
39
|
+
version: '1.6'
|
|
40
40
|
type: :runtime
|
|
41
41
|
prerelease: false
|
|
42
42
|
version_requirements: !ruby/object:Gem::Requirement
|
|
43
43
|
requirements:
|
|
44
44
|
- - "~>"
|
|
45
45
|
- !ruby/object:Gem::Version
|
|
46
|
-
version: '
|
|
46
|
+
version: '1.6'
|
|
47
47
|
- !ruby/object:Gem::Dependency
|
|
48
|
-
name:
|
|
48
|
+
name: ice_nine
|
|
49
49
|
requirement: !ruby/object:Gem::Requirement
|
|
50
50
|
requirements:
|
|
51
51
|
- - "~>"
|
|
52
52
|
- !ruby/object:Gem::Version
|
|
53
|
-
version: '
|
|
53
|
+
version: '0.11'
|
|
54
54
|
type: :runtime
|
|
55
55
|
prerelease: false
|
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
|
57
57
|
requirements:
|
|
58
58
|
- - "~>"
|
|
59
59
|
- !ruby/object:Gem::Version
|
|
60
|
-
version: '
|
|
60
|
+
version: '0.11'
|
|
61
61
|
- !ruby/object:Gem::Dependency
|
|
62
|
-
name:
|
|
62
|
+
name: zeitwerk
|
|
63
63
|
requirement: !ruby/object:Gem::Requirement
|
|
64
64
|
requirements:
|
|
65
65
|
- - "~>"
|
|
66
66
|
- !ruby/object:Gem::Version
|
|
67
|
-
version: '
|
|
67
|
+
version: '2.6'
|
|
68
68
|
type: :runtime
|
|
69
69
|
prerelease: false
|
|
70
70
|
version_requirements: !ruby/object:Gem::Requirement
|
|
71
71
|
requirements:
|
|
72
72
|
- - "~>"
|
|
73
73
|
- !ruby/object:Gem::Version
|
|
74
|
-
version: '
|
|
74
|
+
version: '2.6'
|
|
75
75
|
- !ruby/object:Gem::Dependency
|
|
76
76
|
name: bundler
|
|
77
77
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -158,7 +158,7 @@ licenses:
|
|
|
158
158
|
- MIT
|
|
159
159
|
metadata:
|
|
160
160
|
allowed_push_host: https://rubygems.org
|
|
161
|
-
changelog_uri: https://github.com/dry-rb/dry-struct/blob/
|
|
161
|
+
changelog_uri: https://github.com/dry-rb/dry-struct/blob/main/CHANGELOG.md
|
|
162
162
|
source_code_uri: https://github.com/dry-rb/dry-struct
|
|
163
163
|
bug_tracker_uri: https://github.com/dry-rb/dry-struct/issues
|
|
164
164
|
post_install_message:
|
|
@@ -169,14 +169,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
169
169
|
requirements:
|
|
170
170
|
- - ">="
|
|
171
171
|
- !ruby/object:Gem::Version
|
|
172
|
-
version: 2.
|
|
172
|
+
version: 2.7.0
|
|
173
173
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
174
174
|
requirements:
|
|
175
175
|
- - ">="
|
|
176
176
|
- !ruby/object:Gem::Version
|
|
177
177
|
version: '0'
|
|
178
178
|
requirements: []
|
|
179
|
-
rubygems_version: 3.
|
|
179
|
+
rubygems_version: 3.1.6
|
|
180
180
|
signing_key:
|
|
181
181
|
specification_version: 4
|
|
182
182
|
summary: Typed structs and value objects
|