dry-initializer 2.5.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.rubocop.yml +7 -7
- data/.travis.yml +8 -4
- data/CHANGELOG.md +99 -11
- data/Gemfile +1 -1
- data/README.md +0 -1
- data/dry-initializer.gemspec +2 -2
- data/lib/dry/initializer.rb +9 -7
- data/lib/dry/initializer/config.rb +19 -7
- data/lib/dry/initializer/definition.rb +11 -62
- data/lib/dry/initializer/dispatchers.rb +101 -33
- data/lib/dry/initializer/dispatchers/build_nested_type.rb +58 -0
- data/lib/dry/initializer/dispatchers/check_type.rb +43 -0
- data/lib/dry/initializer/dispatchers/prepare_default.rb +40 -0
- data/lib/dry/initializer/dispatchers/prepare_ivar.rb +12 -0
- data/lib/dry/initializer/dispatchers/prepare_optional.rb +13 -0
- data/lib/dry/initializer/dispatchers/prepare_reader.rb +30 -0
- data/lib/dry/initializer/dispatchers/prepare_source.rb +28 -0
- data/lib/dry/initializer/dispatchers/prepare_target.rb +44 -0
- data/lib/dry/initializer/dispatchers/unwrap_type.rb +22 -0
- data/lib/dry/initializer/dispatchers/wrap_type.rb +27 -0
- data/lib/dry/initializer/struct.rb +40 -0
- data/lib/dry/initializer/undefined.rb +2 -0
- data/spec/definition_spec.rb +6 -2
- data/spec/list_type_spec.rb +32 -0
- data/spec/nested_type_spec.rb +44 -0
- data/spec/spec_helper.rb +2 -1
- data/spec/type_constraint_spec.rb +3 -3
- metadata +20 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d65124ac530b85023e9152387677a694f2cab063b484ba48133ed8006fc79c2a
|
4
|
+
data.tar.gz: e35526cc7df9ad5271485742f75991e397c06c04af8029003ebdd567974f763c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ad262ac79a0191fdaee557a4d1f1b48fbb3c3dc57af0cd639077277dffe52fcecb979db69af0b5f00c803006ceab893d7a057ae085006fc343ef742e2b6f0a2a
|
7
|
+
data.tar.gz: 7b79bd6d05a8a9a7bb239b35cd12629dbd8eda35721916d06b7d04dac7639d361f04958e3a3ace67f5267163c27ae983ad4cb63bbf003efc96cdcf25d9028099
|
data/.rubocop.yml
CHANGED
@@ -10,13 +10,17 @@ AllCops:
|
|
10
10
|
Bundler/DuplicatedGem:
|
11
11
|
Enabled: false
|
12
12
|
|
13
|
+
Naming/FileName:
|
14
|
+
Exclude:
|
15
|
+
- lib/dry-initializer.rb
|
16
|
+
|
13
17
|
Style/CaseEquality:
|
14
18
|
Enabled: false
|
15
19
|
|
16
|
-
Style/
|
20
|
+
Style/ClassAndModuleChildren:
|
17
21
|
Enabled: false
|
18
22
|
|
19
|
-
Style/
|
23
|
+
Style/ClassVars:
|
20
24
|
Enabled: false
|
21
25
|
|
22
26
|
Style/Documentation:
|
@@ -25,10 +29,6 @@ Style/Documentation:
|
|
25
29
|
Style/DoubleNegation:
|
26
30
|
Enabled: false
|
27
31
|
|
28
|
-
Style/FileName:
|
29
|
-
Exclude:
|
30
|
-
- lib/dry-initializer.rb
|
31
|
-
|
32
32
|
Style/Lambda:
|
33
33
|
Exclude:
|
34
34
|
- spec/**/*.rb
|
@@ -36,7 +36,7 @@ Style/Lambda:
|
|
36
36
|
Style/LambdaCall:
|
37
37
|
Enabled: false
|
38
38
|
|
39
|
-
Style/
|
39
|
+
Style/RescueModifier:
|
40
40
|
Exclude:
|
41
41
|
- spec/**/*.rb
|
42
42
|
|
data/.travis.yml
CHANGED
@@ -1,16 +1,19 @@
|
|
1
1
|
---
|
2
2
|
language: ruby
|
3
|
-
sudo: false
|
4
3
|
cache: bundler
|
5
4
|
bundler_args: --without benchmarks tools
|
6
5
|
script:
|
7
6
|
- bundle exec rake spec
|
8
7
|
rvm:
|
9
|
-
- 2.3.
|
10
|
-
- 2.4.
|
8
|
+
- 2.3.8
|
9
|
+
- 2.4.6
|
10
|
+
- 2.5.5
|
11
|
+
- 2.6.2
|
12
|
+
- jruby-9.2.7.0
|
11
13
|
- jruby-9000
|
12
14
|
- rbx-3
|
13
15
|
- ruby-head
|
16
|
+
- truffleruby
|
14
17
|
env:
|
15
18
|
global:
|
16
19
|
- JRUBY_OPTS='--dev -J-Xmx1024M'
|
@@ -19,6 +22,7 @@ matrix:
|
|
19
22
|
- rvm: rbx-3
|
20
23
|
- rvm: ruby-head
|
21
24
|
- rvm: jruby-head
|
25
|
+
- rvm: truffleruby
|
22
26
|
include:
|
23
27
|
- rvm: jruby-head
|
24
|
-
before_install: gem install bundler --no-
|
28
|
+
before_install: gem install bundler --no-document
|
data/CHANGELOG.md
CHANGED
@@ -5,6 +5,89 @@ All notable changes to this project will be documented in this file.
|
|
5
5
|
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
6
6
|
and this project adheres to [Semantic Versioning](http://semver.org/).
|
7
7
|
|
8
|
+
## [3.0.0] [2019-04-14]
|
9
|
+
|
10
|
+
### Added
|
11
|
+
|
12
|
+
- Support of wrapped types/coercers (nepalez)
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
class Test
|
16
|
+
# Wrap type to the array
|
17
|
+
param :foo, [proc(&:to_s)]
|
18
|
+
end
|
19
|
+
|
20
|
+
# And the value will be wrapped as well
|
21
|
+
test = Test.new(42)
|
22
|
+
test.foo # => ["42"]
|
23
|
+
```
|
24
|
+
|
25
|
+
- It works with several layers of nesting (nepalez)
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
class Test
|
29
|
+
# Wrap type to the array
|
30
|
+
param :foo, [[proc(&:to_s)]]
|
31
|
+
end
|
32
|
+
|
33
|
+
# And the value will be wrapped as well
|
34
|
+
test = Test.new(42)
|
35
|
+
test.foo # => [["42"]]
|
36
|
+
```
|
37
|
+
|
38
|
+
- Support of nested types/coercers (nepalez)
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
class Test
|
42
|
+
param :foo do
|
43
|
+
option :bar do
|
44
|
+
option :baz, proc(&:to_s)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
test = Test.new(bar: { "baz" => 42 })
|
50
|
+
test.foo.bar.baz # => "42"
|
51
|
+
```
|
52
|
+
|
53
|
+
- Wrapped/nested combinations are supported as well (nepalez)
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
class Test
|
57
|
+
param :foo, [] do
|
58
|
+
option :bar, proc(&:to_s)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
test = Test.new(bar: 42)
|
63
|
+
test.foo.first.bar # => "42"
|
64
|
+
```
|
65
|
+
|
66
|
+
## [2.7.0] Unreleazed
|
67
|
+
|
68
|
+
### Fixed
|
69
|
+
|
70
|
+
- Roll back master to the state of [2.5.0].
|
71
|
+
|
72
|
+
Somehow distinction between `@default_null` and `@null` variables
|
73
|
+
in the `Dry::Initializer::Builders` broken the `rom` library.
|
74
|
+
|
75
|
+
The version [2.6.0] has been yanked on rubygems, so the master
|
76
|
+
was rolled back to the previous state until the reason for
|
77
|
+
the incompatibility become clear (bjeanes, nepalez)
|
78
|
+
|
79
|
+
## [2.6.0] [2018-09-09] (YANKED)
|
80
|
+
|
81
|
+
## [2.5.0] [2018-08-17]
|
82
|
+
|
83
|
+
### Fixed
|
84
|
+
|
85
|
+
- `nil` coercion (belousovAV)
|
86
|
+
|
87
|
+
When default value is `nil` instead of `Dry::Initializer::UNDEFINED`,
|
88
|
+
the coercion should be applied to any value, including `nil`, because
|
89
|
+
we cannot distinct "undefined" `nil` from the "assigned" `nil` value.
|
90
|
+
|
8
91
|
## [2.4.0] [2018-02-01]
|
9
92
|
|
10
93
|
### Added
|
@@ -367,18 +450,20 @@ and to @gzigzigzeo for persuading me to do this refactoring.
|
|
367
450
|
### Added
|
368
451
|
- enhancement via `Dry::Initializer::Attribute.dispatchers` registry (nepalez)
|
369
452
|
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
453
|
+
```ruby
|
454
|
+
# Register dispatcher for `:string` option
|
455
|
+
Dry::Initializer::Attribute.dispatchers << ->(string: nil, **op) do
|
456
|
+
string ? op.merge(type: proc(&:to_s)) : op
|
457
|
+
end
|
374
458
|
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
459
|
+
# Now you can use the `:string` key for `param` and `option`
|
460
|
+
class User
|
461
|
+
extend Dry::Initializer
|
462
|
+
param :name, string: true
|
463
|
+
end
|
380
464
|
|
381
|
-
|
465
|
+
User.new(:Andy).name # => "Andy"
|
466
|
+
```
|
382
467
|
|
383
468
|
### Changed
|
384
469
|
- optimize assignments for performance (nepalez)
|
@@ -757,4 +842,7 @@ First public release
|
|
757
842
|
[2.1.0]: https://github.com/dry-rb/dry-initializer/compare/v2.0.0...v2.1.0
|
758
843
|
[2.2.0]: https://github.com/dry-rb/dry-initializer/compare/v2.1.0...v2.2.0
|
759
844
|
[2.3.0]: https://github.com/dry-rb/dry-initializer/compare/v2.2.0...v2.3.0
|
760
|
-
[2.4.0]: https://github.com/dry-rb/dry-initializer/compare/v2.3.0...v2.4.0
|
845
|
+
[2.4.0]: https://github.com/dry-rb/dry-initializer/compare/v2.3.0...v2.4.0
|
846
|
+
[2.6.0]: https://github.com/dry-rb/dry-initializer/compare/v2.4.0...v2.5.0
|
847
|
+
[2.6.0]: https://github.com/dry-rb/dry-initializer/compare/v2.5.0...v2.6.0
|
848
|
+
[3.0.0]: https://github.com/dry-rb/dry-initializer/compare/v2.5.0...v3.0.0
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/dry-initializer.svg)][gem]
|
4
4
|
[![Build Status](https://travis-ci.org/dry-rb/dry-initializer.svg?branch=master)][travis]
|
5
|
-
[![Dependency Status](https://gemnasium.com/dry-rb/dry-initializer.svg)][gemnasium]
|
6
5
|
[![Code Climate](https://codeclimate.com/github/dry-rb/dry-initializer/badges/gpa.svg)][codeclimate]
|
7
6
|
[![Test Coverage](https://codeclimate.com/github/dry-rb/dry-initializer/badges/coverage.svg)][coveralls]
|
8
7
|
[![Inline docs](http://inch-ci.org/github/dry-rb/dry-initializer.svg?branch=master)][inchpages]
|
data/dry-initializer.gemspec
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
Gem::Specification.new do |gem|
|
2
2
|
gem.name = "dry-initializer"
|
3
|
-
gem.version = "
|
3
|
+
gem.version = "3.0.0"
|
4
4
|
gem.author = ["Vladimir Kochnev (marshall-lee)", "Andrew Kozin (nepalez)"]
|
5
5
|
gem.email = "andrew.kozin@gmail.com"
|
6
|
-
gem.homepage = "https://github.com/
|
6
|
+
gem.homepage = "https://github.com/dry-rb/dry-initializer"
|
7
7
|
gem.summary = "DSL for declaring params and options of the initializer"
|
8
8
|
gem.license = "MIT"
|
9
9
|
|
data/lib/dry/initializer.rb
CHANGED
@@ -6,9 +6,7 @@ module Dry
|
|
6
6
|
# DSL for declaring params and options of class initializers
|
7
7
|
#
|
8
8
|
module Initializer
|
9
|
-
|
10
|
-
UNDEFINED = Object.new.freeze
|
11
|
-
|
9
|
+
require_relative "initializer/undefined"
|
12
10
|
require_relative "initializer/dsl"
|
13
11
|
require_relative "initializer/definition"
|
14
12
|
require_relative "initializer/builders"
|
@@ -32,18 +30,20 @@ module Dry
|
|
32
30
|
# @option opts [Boolean] :optional
|
33
31
|
# @option opts [Symbol] :as
|
34
32
|
# @option opts [true, false, :protected, :public, :private] :reader
|
33
|
+
# @yield block with nested definition
|
35
34
|
# @return [self] itself
|
36
|
-
def param(name, type = nil, **opts)
|
37
|
-
dry_initializer.param(name, type,
|
35
|
+
def param(name, type = nil, **opts, &block)
|
36
|
+
dry_initializer.param(name, type, **opts, &block)
|
38
37
|
self
|
39
38
|
end
|
40
39
|
|
41
40
|
# Adds or redefines an option of [#dry_initializer]
|
42
41
|
# @param (see #param)
|
43
42
|
# @option (see #param)
|
43
|
+
# @yield (see #param)
|
44
44
|
# @return (see #param)
|
45
|
-
def option(name, type = nil, **opts)
|
46
|
-
dry_initializer.option(name, type,
|
45
|
+
def option(name, type = nil, **opts, &block)
|
46
|
+
dry_initializer.option(name, type, **opts, &block)
|
47
47
|
self
|
48
48
|
end
|
49
49
|
|
@@ -55,5 +55,7 @@ module Dry
|
|
55
55
|
klass.send(:instance_variable_set, :@dry_initializer, config)
|
56
56
|
dry_initializer.children << config
|
57
57
|
end
|
58
|
+
|
59
|
+
require_relative "initializer/struct"
|
58
60
|
end
|
59
61
|
end
|
@@ -57,8 +57,8 @@ module Dry::Initializer
|
|
57
57
|
# @option opts [Symbol] :as
|
58
58
|
# @option opts [true, false, :protected, :public, :private] :reader
|
59
59
|
# @return [self] itself
|
60
|
-
def param(name, type = nil, **opts)
|
61
|
-
add_definition(false, name, type, opts)
|
60
|
+
def param(name, type = nil, **opts, &block)
|
61
|
+
add_definition(false, name, type, block, opts)
|
62
62
|
end
|
63
63
|
|
64
64
|
# Adds or redefines an option of [#dry_initializer]
|
@@ -67,8 +67,8 @@ module Dry::Initializer
|
|
67
67
|
# @option (see #param)
|
68
68
|
# @return (see #param)
|
69
69
|
#
|
70
|
-
def option(name, type = nil, **opts)
|
71
|
-
add_definition(true, name, type, opts)
|
70
|
+
def option(name, type = nil, **opts, &block)
|
71
|
+
add_definition(true, name, type, block, opts)
|
72
72
|
end
|
73
73
|
|
74
74
|
# The hash of public attributes for an instance of the [#extended_class]
|
@@ -133,13 +133,25 @@ module Dry::Initializer
|
|
133
133
|
finalize
|
134
134
|
end
|
135
135
|
|
136
|
-
|
137
|
-
|
136
|
+
# rubocop: disable Metrics/MethodLength
|
137
|
+
def add_definition(option, name, type, block, **opts)
|
138
|
+
opts = {
|
139
|
+
parent: extended_class,
|
140
|
+
option: option,
|
141
|
+
null: null,
|
142
|
+
source: name,
|
143
|
+
type: type,
|
144
|
+
block: block,
|
145
|
+
**opts,
|
146
|
+
}
|
147
|
+
|
148
|
+
options = Dispatchers.call(opts)
|
149
|
+
definition = Definition.new(options)
|
138
150
|
definitions[definition.source] = definition
|
139
151
|
finalize
|
140
|
-
|
141
152
|
mixin.class_eval definition.code
|
142
153
|
end
|
154
|
+
# rubocop: enable Metrics/MethodLength
|
143
155
|
|
144
156
|
def final_definitions
|
145
157
|
parent_definitions = Hash(parent&.definitions&.dup)
|
@@ -49,68 +49,17 @@ module Dry::Initializer
|
|
49
49
|
|
50
50
|
private
|
51
51
|
|
52
|
-
def initialize(
|
53
|
-
@option =
|
54
|
-
@null = null
|
55
|
-
@source = source
|
56
|
-
@target =
|
57
|
-
@ivar =
|
58
|
-
@type =
|
59
|
-
@reader =
|
60
|
-
@default =
|
61
|
-
@optional = options
|
62
|
-
@desc = options[:desc]
|
52
|
+
def initialize(**options)
|
53
|
+
@option = options[:option]
|
54
|
+
@null = options[:null]
|
55
|
+
@source = options[:source]
|
56
|
+
@target = options[:target]
|
57
|
+
@ivar = "@#{@target}"
|
58
|
+
@type = options[:type]
|
59
|
+
@reader = options[:reader]
|
60
|
+
@default = options[:default]
|
61
|
+
@optional = options[:optional]
|
62
|
+
@desc = options[:desc]
|
63
63
|
end
|
64
|
-
|
65
|
-
def check_source(value)
|
66
|
-
if RESERVED.include? value
|
67
|
-
raise ArgumentError, "Name #{value} is reserved by dry-initializer gem"
|
68
|
-
end
|
69
|
-
|
70
|
-
unless option || value[ATTRIBUTE]
|
71
|
-
raise ArgumentError, "Invalid parameter name :'#{value}'"
|
72
|
-
end
|
73
|
-
|
74
|
-
value
|
75
|
-
end
|
76
|
-
|
77
|
-
def check_target(value)
|
78
|
-
return value if value[ATTRIBUTE]
|
79
|
-
raise ArgumentError, "Invalid variable name :'#{value}'"
|
80
|
-
end
|
81
|
-
|
82
|
-
def check_type(value)
|
83
|
-
return if value.nil?
|
84
|
-
arity = value.arity if value.is_a? Proc
|
85
|
-
arity ||= value.method(:call).arity if value.respond_to? :call
|
86
|
-
return value if [1, 2].include? arity.to_i.abs
|
87
|
-
raise TypeError,
|
88
|
-
"type of #{inspect} should respond to #call with 1..2 arguments"
|
89
|
-
end
|
90
|
-
|
91
|
-
def check_default(value)
|
92
|
-
return if value.nil?
|
93
|
-
return value if value.is_a?(Proc) && value.arity < 1
|
94
|
-
raise TypeError,
|
95
|
-
"default value of #{inspect} should be a proc without params"
|
96
|
-
end
|
97
|
-
|
98
|
-
def prepare_reader(value)
|
99
|
-
case value.to_s
|
100
|
-
when "", "false" then false
|
101
|
-
when "private" then :private
|
102
|
-
when "protected" then :protected
|
103
|
-
else :public
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
ATTRIBUTE = /\A\w+\z/
|
108
|
-
RESERVED = %i[
|
109
|
-
__dry_initializer_options__
|
110
|
-
__dry_initializer_config__
|
111
|
-
__dry_initializer_value__
|
112
|
-
__dry_initializer_definition__
|
113
|
-
__dry_initializer_initializer__
|
114
|
-
].freeze
|
115
64
|
end
|
116
65
|
end
|
@@ -1,44 +1,112 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
#
|
2
|
+
# The module is responsible for __normalizing__ arguments
|
3
|
+
# of `.param` and `.option`.
|
4
|
+
#
|
5
|
+
# What the module does is convert the source list of arguments
|
6
|
+
# into the standard set of options:
|
7
|
+
# - `:option` -- whether an argument is an option (or param)
|
8
|
+
# - `:source` -- the name of source option
|
9
|
+
# - `:target` -- the target name of the reader
|
10
|
+
# - `:reader` -- if the reader's privacy (:public, :protected, :private, nil)
|
11
|
+
# - `:ivar` -- the target nane of the variable
|
12
|
+
# - `:type` -- the callable coercer of the source value
|
13
|
+
# - `:optional` -- if the argument is optional
|
14
|
+
# - `:default` -- the proc returning the default value of the source value
|
15
|
+
# - `:null` -- the value to be set to unassigned optional argument
|
16
|
+
#
|
17
|
+
# It is this set is used to build [Dry::Initializer::Definition].
|
18
|
+
#
|
19
|
+
# @example
|
20
|
+
# # from `option :foo, [], as: :bar, optional: :true
|
21
|
+
# input = { name: :foo, as: :bar, type: [], optional: true }
|
22
|
+
#
|
23
|
+
# Dry::Initializer::Dispatcher.call(input)
|
24
|
+
# # => {
|
25
|
+
# # source: "foo",
|
26
|
+
# # target: "bar",
|
27
|
+
# # reader: :public,
|
28
|
+
# # ivar: "@bar",
|
29
|
+
# # type: ->(v) { Array(v) } }, # simplified for brevity
|
30
|
+
# # optional: true,
|
31
|
+
# # default: -> { Dry::Initializer::UNDEFINED },
|
32
|
+
# # }
|
33
|
+
#
|
34
|
+
# # Settings
|
35
|
+
#
|
36
|
+
# The module uses global setting `null` to define what value
|
37
|
+
# should be set to variables that kept unassigned. By default it
|
38
|
+
# uses `Dry::Initializer::UNDEFINED`
|
39
|
+
#
|
40
|
+
# # Syntax Extensions
|
41
|
+
#
|
42
|
+
# The module supports syntax extensions. You can add any number
|
43
|
+
# of custom dispatchers __on top__ of the stack of default dispatchers.
|
44
|
+
# Every dispatcher should be a callable object that takes
|
45
|
+
# the source set of options and converts it to another set of options.
|
46
|
+
#
|
47
|
+
# @example Add special dispatcher
|
48
|
+
#
|
49
|
+
# # Define a dispatcher for key :integer
|
50
|
+
# dispatcher = proc do |integer: false, **opts|
|
51
|
+
# opts.merge(type: proc(&:to_i)) if integer
|
52
|
+
# end
|
53
|
+
#
|
54
|
+
# # Register a dispatcher
|
55
|
+
# Dry::Initializer::Dispatchers << dispatcher
|
56
|
+
#
|
57
|
+
# # Now you can use option `integer: true` instead of `type: proc(&:to_i)`
|
58
|
+
# class Foo
|
59
|
+
# extend Dry::Initializer
|
60
|
+
# param :id, integer: true
|
61
|
+
# end
|
62
|
+
#
|
63
|
+
module Dry::Initializer::Dispatchers
|
64
|
+
extend self
|
65
|
+
|
66
|
+
# @!attribute [rw] null Defines a value to be set to unassigned attributes
|
67
|
+
# @return [Object]
|
68
|
+
attr_accessor :null
|
69
|
+
|
6
70
|
#
|
7
|
-
#
|
8
|
-
# the resulting hash so that you can send additional keys to the helpers.
|
71
|
+
# Registers a new dispatcher
|
9
72
|
#
|
10
|
-
# @
|
73
|
+
# @param [#call] dispatcher
|
74
|
+
# @return [self] itself
|
11
75
|
#
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
76
|
+
def <<(dispatcher)
|
77
|
+
@pipeline = [dispatcher] + pipeline
|
78
|
+
self
|
79
|
+
end
|
80
|
+
|
16
81
|
#
|
17
|
-
#
|
18
|
-
# Dry::Initializer::Dispatchers << dispatcher
|
82
|
+
# Normalizes the source set of options
|
19
83
|
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
# extend Dry::Initializer
|
23
|
-
# param :id, integer: true
|
24
|
-
# end
|
84
|
+
# @param [Hash<Symbol, Object>] options
|
85
|
+
# @return [Hash<Symbol, Objct>] normalized set of options
|
25
86
|
#
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
self
|
31
|
-
end
|
87
|
+
def call(**options)
|
88
|
+
options = { null: null }.merge(options)
|
89
|
+
pipeline.reduce(options) { |opts, dispatcher| dispatcher.call(opts) }
|
90
|
+
end
|
32
91
|
|
33
|
-
|
34
|
-
list.inject(options) { |opts, item| item.call(opts) }
|
35
|
-
end
|
92
|
+
private
|
36
93
|
|
37
|
-
|
94
|
+
require_relative "dispatchers/build_nested_type"
|
95
|
+
require_relative "dispatchers/check_type"
|
96
|
+
require_relative "dispatchers/prepare_default"
|
97
|
+
require_relative "dispatchers/prepare_ivar"
|
98
|
+
require_relative "dispatchers/prepare_optional"
|
99
|
+
require_relative "dispatchers/prepare_reader"
|
100
|
+
require_relative "dispatchers/prepare_source"
|
101
|
+
require_relative "dispatchers/prepare_target"
|
102
|
+
require_relative "dispatchers/unwrap_type"
|
103
|
+
require_relative "dispatchers/wrap_type"
|
38
104
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
105
|
+
def pipeline
|
106
|
+
@pipeline ||= [
|
107
|
+
PrepareSource, PrepareTarget, PrepareIvar, PrepareReader,
|
108
|
+
PrepareDefault, PrepareOptional,
|
109
|
+
UnwrapType, CheckType, BuildNestedType, WrapType
|
110
|
+
]
|
43
111
|
end
|
44
112
|
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
#
|
2
|
+
# Prepare nested data type from a block
|
3
|
+
#
|
4
|
+
# @example
|
5
|
+
# option :foo do
|
6
|
+
# option :bar
|
7
|
+
# option :qux
|
8
|
+
# end
|
9
|
+
#
|
10
|
+
module Dry::Initializer::Dispatchers::BuildNestedType
|
11
|
+
extend self
|
12
|
+
|
13
|
+
# rubocop: disable Metrics/ParameterLists
|
14
|
+
def call(parent:, source:, target:, type: nil, block: nil, **options)
|
15
|
+
check_certainty!(source, type, block)
|
16
|
+
check_name!(target)
|
17
|
+
type ||= build_nested_type(parent, target, block)
|
18
|
+
{ parent: parent, source: source, target: target, type: type, **options }
|
19
|
+
end
|
20
|
+
# rubocop: enable Metrics/ParameterLists
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def check_certainty!(source, type, block)
|
25
|
+
return unless type
|
26
|
+
return unless block
|
27
|
+
|
28
|
+
raise ArgumentError, <<~MESSAGE
|
29
|
+
You should define coercer of values of argument '#{source}'
|
30
|
+
either though the parameter/option, or via nested block, but not the both.
|
31
|
+
MESSAGE
|
32
|
+
end
|
33
|
+
|
34
|
+
def check_name!(name)
|
35
|
+
return unless name[/^_|__|_$/]
|
36
|
+
|
37
|
+
raise ArgumentError, <<~MESSAGE
|
38
|
+
The name of the argument '#{name}' cannot be used for nested struct.
|
39
|
+
A proper name can use underscores _ to divide alphanumeric parts only.
|
40
|
+
MESSAGE
|
41
|
+
end
|
42
|
+
|
43
|
+
def build_nested_type(parent, name, block)
|
44
|
+
return unless block
|
45
|
+
|
46
|
+
klass_name = full_name(parent, name)
|
47
|
+
build_struct(klass_name, block)
|
48
|
+
end
|
49
|
+
|
50
|
+
def full_name(parent, name)
|
51
|
+
"::#{parent.name}::#{name.to_s.split("_").compact.map(&:capitalize).join}"
|
52
|
+
end
|
53
|
+
|
54
|
+
def build_struct(klass_name, block)
|
55
|
+
eval "class #{klass_name} < Dry::Initializer::Struct; end"
|
56
|
+
const_get(klass_name).tap { |klass| klass.class_eval(&block) }
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
#
|
2
|
+
# Checks whether an unwrapped type is valid
|
3
|
+
#
|
4
|
+
module Dry::Initializer::Dispatchers::CheckType
|
5
|
+
extend self
|
6
|
+
|
7
|
+
def call(source:, type: nil, wrap: 0, **options)
|
8
|
+
check_if_callable! source, type
|
9
|
+
check_arity! source, type, wrap
|
10
|
+
|
11
|
+
{ source: source, type: type, wrap: wrap, **options }
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def check_if_callable!(source, type)
|
17
|
+
return if type.nil?
|
18
|
+
return if type.respond_to?(:call)
|
19
|
+
|
20
|
+
raise ArgumentError,
|
21
|
+
"The type of the argument '#{source}' should be callable"
|
22
|
+
end
|
23
|
+
|
24
|
+
def check_arity!(_source, type, wrap)
|
25
|
+
return if type.nil?
|
26
|
+
return if wrap.zero?
|
27
|
+
return if type.method(:call).arity.abs == 1
|
28
|
+
|
29
|
+
raise ArgumentError, <<~MESSAGE
|
30
|
+
The dry_intitializer supports wrapped types with one argument only.
|
31
|
+
You cannot use array types with element coercers having several arguments.
|
32
|
+
|
33
|
+
For example, this definitions are correct:
|
34
|
+
option :foo, [proc(&:to_s)]
|
35
|
+
option :bar, type: [[]]
|
36
|
+
option :baz, ->(a, b) { [a, b] }
|
37
|
+
|
38
|
+
While this is not:
|
39
|
+
option :foo, [->(a, b) { [a, b] }]
|
40
|
+
MESSAGE
|
41
|
+
end
|
42
|
+
# rubocop: enable Metrics/MethodLength
|
43
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
#
|
2
|
+
# Prepares the `:default` option
|
3
|
+
#
|
4
|
+
# It must respond to `.call` without arguments
|
5
|
+
#
|
6
|
+
module Dry::Initializer::Dispatchers::PrepareDefault
|
7
|
+
extend self
|
8
|
+
|
9
|
+
def call(default: nil, optional: nil, **options)
|
10
|
+
default = callable! default
|
11
|
+
check_arity! default
|
12
|
+
|
13
|
+
{ default: default, optional: (optional | default), **options }
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def callable!(default)
|
19
|
+
return unless default
|
20
|
+
return default if default.respond_to?(:call)
|
21
|
+
return callable(default.to_proc) if default.respond_to?(:to_proc)
|
22
|
+
|
23
|
+
invalid!(default)
|
24
|
+
end
|
25
|
+
|
26
|
+
def check_arity!(default)
|
27
|
+
return unless default
|
28
|
+
|
29
|
+
arity = default.method(:call).arity.to_i
|
30
|
+
return unless arity.positive?
|
31
|
+
|
32
|
+
invalid!(default)
|
33
|
+
end
|
34
|
+
|
35
|
+
def invalid!(default)
|
36
|
+
raise TypeError, "The #{default.inspect} should be" \
|
37
|
+
" either convertable to proc with no arguments," \
|
38
|
+
" or respond to #call without arguments."
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
#
|
2
|
+
# Prepares the variable name of a parameter or an option.
|
3
|
+
#
|
4
|
+
module Dry::Initializer::Dispatchers::PrepareIvar
|
5
|
+
module_function
|
6
|
+
|
7
|
+
def call(target:, **options)
|
8
|
+
ivar = "@#{target}".delete("?").to_sym
|
9
|
+
|
10
|
+
{ target: target, ivar: ivar, **options }
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
#
|
2
|
+
# Defines whether an argument is optional
|
3
|
+
#
|
4
|
+
module Dry::Initializer::Dispatchers::PrepareOptional
|
5
|
+
module_function
|
6
|
+
|
7
|
+
def call(optional: nil, default: nil, required: nil, **options)
|
8
|
+
optional ||= default
|
9
|
+
optional &&= !required
|
10
|
+
|
11
|
+
{ optional: !!optional, default: default, **options }
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
#
|
2
|
+
# Checks the reader privacy
|
3
|
+
#
|
4
|
+
module Dry::Initializer::Dispatchers::PrepareReader
|
5
|
+
extend self
|
6
|
+
|
7
|
+
def call(target: nil, reader: :public, **options)
|
8
|
+
reader = case reader.to_s
|
9
|
+
when "false", "" then nil
|
10
|
+
when "true" then :public
|
11
|
+
when "public", "private", "protected" then reader.to_sym
|
12
|
+
else invalid_reader!(target, reader)
|
13
|
+
end
|
14
|
+
|
15
|
+
{ target: target, reader: reader, **options }
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def invalid_reader!(target, _reader)
|
21
|
+
raise ArgumentError, <<~MESSAGE
|
22
|
+
Invalid setting for the ##{target} reader's privacy.
|
23
|
+
Use the one of the following values for the `:reader` option:
|
24
|
+
- 'public' (true) for the public reader (default)
|
25
|
+
- 'private' for the private reader
|
26
|
+
- 'protected' for the protected reader
|
27
|
+
- nil (false) if no reader should be defined
|
28
|
+
MESSAGE
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#
|
2
|
+
# The dispatcher verifies a correctness of the source name
|
3
|
+
# of param or option, taken as a `:source` option.
|
4
|
+
#
|
5
|
+
# We allow any stringified name for the source.
|
6
|
+
# For example, this syntax is correct because we accept any key
|
7
|
+
# in the original hash of arguments, but give them proper names:
|
8
|
+
#
|
9
|
+
# ```ruby
|
10
|
+
# class Foo
|
11
|
+
# extend Dry::Initializer
|
12
|
+
#
|
13
|
+
# option "", as: :first
|
14
|
+
# option 1, as: :second
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# foo = Foo.new("": 42, 1: 666)
|
18
|
+
# foo.first # => 42
|
19
|
+
# foo.second # => 666
|
20
|
+
# ```
|
21
|
+
#
|
22
|
+
module Dry::Initializer::Dispatchers::PrepareSource
|
23
|
+
module_function
|
24
|
+
|
25
|
+
def call(source:, **options)
|
26
|
+
{ source: source.to_s.to_sym, **options }
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
#
|
2
|
+
# Prepares the target name of a parameter or an option.
|
3
|
+
#
|
4
|
+
# Unlike source, the target must satisfy requirements for Ruby variable names.
|
5
|
+
# It also shouldn't be in conflict with names used by the gem.
|
6
|
+
#
|
7
|
+
module Dry::Initializer::Dispatchers::PrepareTarget
|
8
|
+
extend self
|
9
|
+
|
10
|
+
# List of variable names reserved by the gem
|
11
|
+
RESERVED = %i[
|
12
|
+
__dry_initializer_options__
|
13
|
+
__dry_initializer_config__
|
14
|
+
__dry_initializer_value__
|
15
|
+
__dry_initializer_definition__
|
16
|
+
__dry_initializer_initializer__
|
17
|
+
].freeze
|
18
|
+
|
19
|
+
def call(source:, target: nil, as: nil, **options)
|
20
|
+
target ||= as || source
|
21
|
+
target = target.to_s.to_sym.downcase
|
22
|
+
|
23
|
+
check_ruby_name!(target)
|
24
|
+
check_reserved_names!(target)
|
25
|
+
|
26
|
+
{ source: source, target: target, **options }
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def check_ruby_name!(target)
|
32
|
+
return if target[/\A[[:alpha:]_][[:alnum:]_]*\??\z/u]
|
33
|
+
|
34
|
+
raise ArgumentError,
|
35
|
+
"The name `#{target}` is not allowed for Ruby methods"
|
36
|
+
end
|
37
|
+
|
38
|
+
def check_reserved_names!(target)
|
39
|
+
return unless RESERVED.include?(target)
|
40
|
+
|
41
|
+
raise ArgumentError,
|
42
|
+
"The method name `#{target}` is reserved by the dry-initializer gem"
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
#
|
2
|
+
# Looks at the `:type` option and counts how many nested arrays
|
3
|
+
# it contains around either nil or a callable value.
|
4
|
+
#
|
5
|
+
# The counted number is preserved in the `:wrap` virtual option
|
6
|
+
# used by the [WrapType] dispatcher.
|
7
|
+
#
|
8
|
+
module Dry::Initializer::Dispatchers::UnwrapType
|
9
|
+
extend self
|
10
|
+
|
11
|
+
def call(type: nil, wrap: 0, **options)
|
12
|
+
type, wrap = unwrap(type, 0)
|
13
|
+
|
14
|
+
{ type: type, wrap: wrap, **options }
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def unwrap(type, count)
|
20
|
+
type.is_a?(Array) ? unwrap(type.first, count + 1) : [type, count]
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
#
|
2
|
+
# Takes `:type` and `:wrap` to construct the final value coercer
|
3
|
+
#
|
4
|
+
module Dry::Initializer::Dispatchers::WrapType
|
5
|
+
extend self
|
6
|
+
|
7
|
+
def call(type: nil, wrap: 0, **options)
|
8
|
+
{ type: wrapped_type(type, wrap), **options }
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def wrapped_type(type, count)
|
14
|
+
return type if count.zero?
|
15
|
+
|
16
|
+
->(value) { wrap_value(value, count, type) }
|
17
|
+
end
|
18
|
+
|
19
|
+
def wrap_value(value, count, type)
|
20
|
+
if count.zero?
|
21
|
+
type ? type.call(value) : value
|
22
|
+
else
|
23
|
+
return [wrap_value(value, count - 1, type)] unless value.is_a?(Array)
|
24
|
+
value.map { |item| wrap_value(item, count - 1, type) }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
#
|
2
|
+
# The nested structure that takes nested hashes with indifferent access
|
3
|
+
#
|
4
|
+
class Dry::Initializer::Struct
|
5
|
+
extend Dry::Initializer
|
6
|
+
|
7
|
+
class << self
|
8
|
+
undef_method :param
|
9
|
+
|
10
|
+
def new(options)
|
11
|
+
super Hash(options).transform_keys(&:to_sym)
|
12
|
+
end
|
13
|
+
alias call new
|
14
|
+
end
|
15
|
+
|
16
|
+
#
|
17
|
+
# Represents event data as a nested hash with deeply stringified keys
|
18
|
+
# @return [Hash<String, ...>]
|
19
|
+
#
|
20
|
+
def to_h
|
21
|
+
self
|
22
|
+
.class
|
23
|
+
.dry_initializer
|
24
|
+
.attributes(self)
|
25
|
+
.transform_values { |v| __hashify(v) }
|
26
|
+
.stringify_keys
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def __hashify(value)
|
32
|
+
case value
|
33
|
+
when Hash
|
34
|
+
value.each_with_object({}) { |(k, v), obj| obj[k.to_s] = __hashify(v) }
|
35
|
+
when Array then value.map { |v| __hashify(v) }
|
36
|
+
when Dry::Initializer::Struct then value.to_h
|
37
|
+
else value
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/spec/definition_spec.rb
CHANGED
@@ -22,7 +22,9 @@ describe "definition" do
|
|
22
22
|
[definition.source, definition.options]
|
23
23
|
end
|
24
24
|
|
25
|
-
expect(params).to eq [
|
25
|
+
expect(params).to eq [
|
26
|
+
[:foo, { as: :foo, reader: :public, optional: false }]
|
27
|
+
]
|
26
28
|
end
|
27
29
|
|
28
30
|
it "preservers definition options" do
|
@@ -30,7 +32,9 @@ describe "definition" do
|
|
30
32
|
[definition.source, definition.options]
|
31
33
|
end
|
32
34
|
|
33
|
-
expect(options).to eq [
|
35
|
+
expect(options).to eq [
|
36
|
+
[:bar, { as: :bar, reader: :public, optional: false }]
|
37
|
+
]
|
34
38
|
end
|
35
39
|
end
|
36
40
|
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require "dry-types"
|
2
|
+
|
3
|
+
describe "list type argument" do
|
4
|
+
before do
|
5
|
+
class Test::Foo
|
6
|
+
extend Dry::Initializer
|
7
|
+
param :foo, [proc(&:to_s)]
|
8
|
+
option :bar, [Dry::Types["strict.string"]]
|
9
|
+
option :baz, []
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
context "with single items" do
|
14
|
+
subject { Test::Foo.new(1, bar: "2", baz: { qux: :QUX }) }
|
15
|
+
|
16
|
+
it "coerces and wraps them to arrays" do
|
17
|
+
expect(subject.foo).to eq %w[1]
|
18
|
+
expect(subject.bar).to eq %w[2]
|
19
|
+
expect(subject.baz).to eq [{ qux: :QUX }]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context "with arrays" do
|
24
|
+
subject { Test::Foo.new([1], bar: %w[2], baz: [{ qux: :QUX }]) }
|
25
|
+
|
26
|
+
it "coerces elements" do
|
27
|
+
expect(subject.foo).to eq %w[1]
|
28
|
+
expect(subject.bar).to eq %w[2]
|
29
|
+
expect(subject.baz).to eq [{ qux: :QUX }]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
describe "nested type argument" do
|
2
|
+
subject { Test::Xyz.new("bar" => { "baz" => 42 }) }
|
3
|
+
|
4
|
+
context "with nested definition only" do
|
5
|
+
before do
|
6
|
+
class Test::Xyz
|
7
|
+
extend Dry::Initializer
|
8
|
+
|
9
|
+
param :foo, as: :x do
|
10
|
+
option :bar, as: :y do
|
11
|
+
option :baz, proc(&:to_s), as: :z
|
12
|
+
option :qux, as: :w, optional: true
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
it "builds the type" do
|
19
|
+
expect(subject.x.y.z).to eq "42"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context "with nested and wrapped definitions" do
|
24
|
+
before do
|
25
|
+
class Test::Xyz
|
26
|
+
extend Dry::Initializer
|
27
|
+
|
28
|
+
param :foo, [], as: :x do
|
29
|
+
option :bar, as: :y do
|
30
|
+
option :baz, proc(&:to_s), as: :z
|
31
|
+
option :qux, as: :w, optional: true
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
it "builds the type" do
|
38
|
+
x = subject.x
|
39
|
+
expect(x).to be_instance_of Array
|
40
|
+
|
41
|
+
expect(x.first.y.z).to eq "42"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -42,7 +42,7 @@ describe "type constraint" do
|
|
42
42
|
context "in case of mismatch" do
|
43
43
|
subject { Test::Foo.new 1 }
|
44
44
|
|
45
|
-
it "raises
|
45
|
+
it "raises ArgumentError" do
|
46
46
|
expect { subject }.to raise_error TypeError, /1/
|
47
47
|
end
|
48
48
|
end
|
@@ -66,13 +66,13 @@ describe "type constraint" do
|
|
66
66
|
end
|
67
67
|
|
68
68
|
context "by invalid constraint" do
|
69
|
-
it "raises
|
69
|
+
it "raises ArgumentError" do
|
70
70
|
expect do
|
71
71
|
class Test::Foo
|
72
72
|
extend Dry::Initializer
|
73
73
|
param :foo, type: String
|
74
74
|
end
|
75
|
-
end.to raise_error(
|
75
|
+
end.to raise_error(ArgumentError)
|
76
76
|
end
|
77
77
|
end
|
78
78
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dry-initializer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Vladimir Kochnev (marshall-lee)
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2019-04-14 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
@@ -103,10 +103,22 @@ files:
|
|
103
103
|
- lib/dry/initializer/config.rb
|
104
104
|
- lib/dry/initializer/definition.rb
|
105
105
|
- lib/dry/initializer/dispatchers.rb
|
106
|
+
- lib/dry/initializer/dispatchers/build_nested_type.rb
|
107
|
+
- lib/dry/initializer/dispatchers/check_type.rb
|
108
|
+
- lib/dry/initializer/dispatchers/prepare_default.rb
|
109
|
+
- lib/dry/initializer/dispatchers/prepare_ivar.rb
|
110
|
+
- lib/dry/initializer/dispatchers/prepare_optional.rb
|
111
|
+
- lib/dry/initializer/dispatchers/prepare_reader.rb
|
112
|
+
- lib/dry/initializer/dispatchers/prepare_source.rb
|
113
|
+
- lib/dry/initializer/dispatchers/prepare_target.rb
|
114
|
+
- lib/dry/initializer/dispatchers/unwrap_type.rb
|
115
|
+
- lib/dry/initializer/dispatchers/wrap_type.rb
|
106
116
|
- lib/dry/initializer/dsl.rb
|
107
117
|
- lib/dry/initializer/mixin.rb
|
108
118
|
- lib/dry/initializer/mixin/local.rb
|
109
119
|
- lib/dry/initializer/mixin/root.rb
|
120
|
+
- lib/dry/initializer/struct.rb
|
121
|
+
- lib/dry/initializer/undefined.rb
|
110
122
|
- lib/tasks/benchmark.rake
|
111
123
|
- lib/tasks/profile.rake
|
112
124
|
- spec/attributes_spec.rb
|
@@ -116,7 +128,9 @@ files:
|
|
116
128
|
- spec/default_values_spec.rb
|
117
129
|
- spec/definition_spec.rb
|
118
130
|
- spec/invalid_default_spec.rb
|
131
|
+
- spec/list_type_spec.rb
|
119
132
|
- spec/missed_default_spec.rb
|
133
|
+
- spec/nested_type_spec.rb
|
120
134
|
- spec/optional_spec.rb
|
121
135
|
- spec/options_tolerance_spec.rb
|
122
136
|
- spec/public_attributes_utility_spec.rb
|
@@ -128,7 +142,7 @@ files:
|
|
128
142
|
- spec/type_argument_spec.rb
|
129
143
|
- spec/type_constraint_spec.rb
|
130
144
|
- spec/value_coercion_via_dry_types_spec.rb
|
131
|
-
homepage: https://github.com/
|
145
|
+
homepage: https://github.com/dry-rb/dry-initializer
|
132
146
|
licenses:
|
133
147
|
- MIT
|
134
148
|
metadata: {}
|
@@ -147,8 +161,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
147
161
|
- !ruby/object:Gem::Version
|
148
162
|
version: '0'
|
149
163
|
requirements: []
|
150
|
-
|
151
|
-
rubygems_version: 2.6.14
|
164
|
+
rubygems_version: 3.0.3
|
152
165
|
signing_key:
|
153
166
|
specification_version: 4
|
154
167
|
summary: DSL for declaring params and options of the initializer
|
@@ -160,7 +173,9 @@ test_files:
|
|
160
173
|
- spec/default_values_spec.rb
|
161
174
|
- spec/definition_spec.rb
|
162
175
|
- spec/invalid_default_spec.rb
|
176
|
+
- spec/list_type_spec.rb
|
163
177
|
- spec/missed_default_spec.rb
|
178
|
+
- spec/nested_type_spec.rb
|
164
179
|
- spec/optional_spec.rb
|
165
180
|
- spec/options_tolerance_spec.rb
|
166
181
|
- spec/public_attributes_utility_spec.rb
|