dry-initializer 0.1.1 → 0.2.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/.rubocop.yml +13 -9
- data/CHANGELOG.md +72 -3
- data/LICENSE.txt +1 -1
- data/README.md +7 -279
- data/benchmarks/with_types.rb +2 -0
- data/benchmarks/with_types_and_defaults.rb +2 -0
- data/dry-initializer.gemspec +1 -1
- data/lib/dry/initializer.rb +5 -4
- data/lib/dry/initializer/builder.rb +66 -13
- data/lib/dry/initializer/errors.rb +5 -7
- data/lib/dry/initializer/errors/default_value_error.rb +6 -0
- data/lib/dry/initializer/errors/order_error.rb +7 -0
- data/lib/dry/initializer/errors/plugin_error.rb +6 -0
- data/lib/dry/initializer/errors/{existing_argument_error.rb → redefinition_error.rb} +1 -1
- data/lib/dry/initializer/errors/type_constraint_error.rb +6 -0
- data/lib/dry/initializer/errors/type_error.rb +4 -3
- data/lib/dry/initializer/mixin.rb +7 -7
- data/lib/dry/initializer/plugins.rb +10 -0
- data/lib/dry/initializer/plugins/base.rb +42 -0
- data/lib/dry/initializer/plugins/default_proc.rb +28 -0
- data/lib/dry/initializer/plugins/signature.rb +35 -0
- data/lib/dry/initializer/plugins/type_constraint.rb +58 -0
- data/lib/dry/initializer/plugins/variable_setter.rb +12 -0
- data/lib/dry/initializer/signature.rb +47 -0
- data/spec/dry/container_spec.rb +3 -3
- data/spec/dry/dry_type_constraint_spec.rb +30 -0
- data/spec/dry/invalid_default_spec.rb +1 -1
- data/spec/dry/{proc_type_spec.rb → object_type_constraint_spec.rb} +4 -4
- data/spec/dry/{poro_type_spec.rb → plain_type_constraint_spec.rb} +1 -1
- data/spec/dry/value_coercion_via_dry_types_spec.rb +21 -0
- metadata +29 -25
- data/lib/dry/initializer/argument.rb +0 -96
- data/lib/dry/initializer/arguments.rb +0 -85
- data/lib/dry/initializer/errors/invalid_default_value_error.rb +0 -6
- data/lib/dry/initializer/errors/invalid_type_error.rb +0 -6
- data/lib/dry/initializer/errors/key_error.rb +0 -5
- data/lib/dry/initializer/errors/missed_default_value_error.rb +0 -5
- data/spec/dry/dry_type_spec.rb +0 -25
- data/spec/dry/invalid_type_spec.rb +0 -13
@@ -0,0 +1,47 @@
|
|
1
|
+
module Dry::Initializer
|
2
|
+
# Mutable container for chunks of code describing argument signatures.
|
3
|
+
# Responcible for building the resulting signature for the initializer args.
|
4
|
+
class Signature
|
5
|
+
include Enumerable
|
6
|
+
include Errors
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@list ||= []
|
10
|
+
end
|
11
|
+
|
12
|
+
def add(*args)
|
13
|
+
signature = Plugins::Signature.new(*args)
|
14
|
+
|
15
|
+
validates_uniqueness_of signature
|
16
|
+
validates_order_of signature
|
17
|
+
|
18
|
+
@list << signature
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
def call
|
23
|
+
map(&:call).join(", ")
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def each
|
29
|
+
(@list.select(&:param?) + @list.reject(&:param?)).each do |item|
|
30
|
+
yield item
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def validates_uniqueness_of(signature)
|
35
|
+
return unless include? signature
|
36
|
+
|
37
|
+
fail RedefinitionError.new(signature.name)
|
38
|
+
end
|
39
|
+
|
40
|
+
def validates_order_of(signature)
|
41
|
+
return unless signature.param? && !signature.default?
|
42
|
+
return unless any? { |item| item.param? && item.default? }
|
43
|
+
|
44
|
+
fail OrderError.new(signature.name)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/spec/dry/container_spec.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
describe "
|
2
|
-
context
|
1
|
+
describe "container" do
|
2
|
+
context "with block syntax" do
|
3
3
|
before do
|
4
4
|
class Test::Foo
|
5
5
|
include Dry::Initializer.define {
|
@@ -21,7 +21,7 @@ describe "base example" do
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
-
context
|
24
|
+
context "with lambda syntax" do
|
25
25
|
before do
|
26
26
|
class Test::Foo
|
27
27
|
include Dry::Initializer.define -> do
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "dry-types"
|
2
|
+
|
3
|
+
describe "Dry type constraint" do
|
4
|
+
before do
|
5
|
+
module Test::Types
|
6
|
+
include Dry::Types.module
|
7
|
+
end
|
8
|
+
|
9
|
+
class Test::Foo
|
10
|
+
extend Dry::Initializer::Mixin
|
11
|
+
param :foo, type: Test::Types::Strict::String
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context "in case of mismatch" do
|
16
|
+
subject { Test::Foo.new 1 }
|
17
|
+
|
18
|
+
it "raises TypeError" do
|
19
|
+
expect { subject }.to raise_error TypeError, /1/
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context "in case of match" do
|
24
|
+
subject { Test::Foo.new "foo" }
|
25
|
+
|
26
|
+
it "completes the initialization" do
|
27
|
+
expect { subject }.not_to raise_error
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -1,14 +1,14 @@
|
|
1
|
-
describe "
|
1
|
+
describe "object type constraint" do
|
2
2
|
before do
|
3
3
|
class Test::Foo
|
4
4
|
extend Dry::Initializer::Mixin
|
5
5
|
|
6
|
-
param :foo, type:
|
6
|
+
param :foo, type: /bar/
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
10
10
|
context "in case of mismatch" do
|
11
|
-
subject { Test::Foo.new
|
11
|
+
subject { Test::Foo.new 'baz' }
|
12
12
|
|
13
13
|
it "raises TypeError" do
|
14
14
|
expect { subject }.to raise_error TypeError
|
@@ -16,7 +16,7 @@ describe "proc type" do
|
|
16
16
|
end
|
17
17
|
|
18
18
|
context "in case of match" do
|
19
|
-
subject { Test::Foo.new
|
19
|
+
subject { Test::Foo.new 'barbar' }
|
20
20
|
|
21
21
|
it "completes the initialization" do
|
22
22
|
expect { subject }.not_to raise_error
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require "dry-types"
|
2
|
+
|
3
|
+
describe "value coercion via dry-types" do
|
4
|
+
before do
|
5
|
+
module Test::Types
|
6
|
+
include Dry::Types.module
|
7
|
+
end
|
8
|
+
|
9
|
+
class Test::Foo
|
10
|
+
extend Dry::Initializer::Mixin
|
11
|
+
|
12
|
+
param :foo, type: Test::Types::Coercible::String
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
subject { Test::Foo.new :foo }
|
17
|
+
|
18
|
+
it "coerces values" do
|
19
|
+
expect(subject.foo).to eql "foo"
|
20
|
+
end
|
21
|
+
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: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Vladimir Kochnev (marshall-lee)
|
@@ -9,50 +9,50 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-
|
12
|
+
date: 2016-05-15 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
|
-
name: rspec
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
16
|
requirements:
|
18
17
|
- - "~>"
|
19
18
|
- !ruby/object:Gem::Version
|
20
19
|
version: '3.0'
|
21
20
|
type: :development
|
22
|
-
prerelease: false
|
23
21
|
version_requirements: !ruby/object:Gem::Requirement
|
24
22
|
requirements:
|
25
23
|
- - "~>"
|
26
24
|
- !ruby/object:Gem::Version
|
27
25
|
version: '3.0'
|
26
|
+
name: rspec
|
27
|
+
prerelease: false
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
|
-
name: rake
|
30
29
|
requirement: !ruby/object:Gem::Requirement
|
31
30
|
requirements:
|
32
31
|
- - "~>"
|
33
32
|
- !ruby/object:Gem::Version
|
34
33
|
version: '10.0'
|
35
34
|
type: :development
|
36
|
-
prerelease: false
|
37
35
|
version_requirements: !ruby/object:Gem::Requirement
|
38
36
|
requirements:
|
39
37
|
- - "~>"
|
40
38
|
- !ruby/object:Gem::Version
|
41
39
|
version: '10.0'
|
40
|
+
name: rake
|
41
|
+
prerelease: false
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
|
-
name: dry-types
|
44
43
|
requirement: !ruby/object:Gem::Requirement
|
45
44
|
requirements:
|
46
45
|
- - "~>"
|
47
46
|
- !ruby/object:Gem::Version
|
48
47
|
version: 0.5.1
|
49
48
|
type: :development
|
50
|
-
prerelease: false
|
51
49
|
version_requirements: !ruby/object:Gem::Requirement
|
52
50
|
requirements:
|
53
51
|
- - "~>"
|
54
52
|
- !ruby/object:Gem::Version
|
55
53
|
version: 0.5.1
|
54
|
+
name: dry-types
|
55
|
+
prerelease: false
|
56
56
|
description:
|
57
57
|
email:
|
58
58
|
- hashtable@yandex.ru
|
@@ -85,30 +85,35 @@ files:
|
|
85
85
|
- dry-initializer.gemspec
|
86
86
|
- lib/dry-initializer.rb
|
87
87
|
- lib/dry/initializer.rb
|
88
|
-
- lib/dry/initializer/argument.rb
|
89
|
-
- lib/dry/initializer/arguments.rb
|
90
88
|
- lib/dry/initializer/builder.rb
|
91
89
|
- lib/dry/initializer/errors.rb
|
92
|
-
- lib/dry/initializer/errors/
|
93
|
-
- lib/dry/initializer/errors/
|
94
|
-
- lib/dry/initializer/errors/
|
95
|
-
- lib/dry/initializer/errors/
|
96
|
-
- lib/dry/initializer/errors/
|
90
|
+
- lib/dry/initializer/errors/default_value_error.rb
|
91
|
+
- lib/dry/initializer/errors/order_error.rb
|
92
|
+
- lib/dry/initializer/errors/plugin_error.rb
|
93
|
+
- lib/dry/initializer/errors/redefinition_error.rb
|
94
|
+
- lib/dry/initializer/errors/type_constraint_error.rb
|
97
95
|
- lib/dry/initializer/errors/type_error.rb
|
98
96
|
- lib/dry/initializer/mixin.rb
|
97
|
+
- lib/dry/initializer/plugins.rb
|
98
|
+
- lib/dry/initializer/plugins/base.rb
|
99
|
+
- lib/dry/initializer/plugins/default_proc.rb
|
100
|
+
- lib/dry/initializer/plugins/signature.rb
|
101
|
+
- lib/dry/initializer/plugins/type_constraint.rb
|
102
|
+
- lib/dry/initializer/plugins/variable_setter.rb
|
103
|
+
- lib/dry/initializer/signature.rb
|
99
104
|
- spec/dry/base_spec.rb
|
100
105
|
- spec/dry/container_spec.rb
|
101
106
|
- spec/dry/default_nil_spec.rb
|
102
107
|
- spec/dry/default_values_spec.rb
|
103
|
-
- spec/dry/
|
108
|
+
- spec/dry/dry_type_constraint_spec.rb
|
104
109
|
- spec/dry/invalid_default_spec.rb
|
105
|
-
- spec/dry/invalid_type_spec.rb
|
106
110
|
- spec/dry/missed_default_spec.rb
|
107
|
-
- spec/dry/
|
108
|
-
- spec/dry/
|
111
|
+
- spec/dry/object_type_constraint_spec.rb
|
112
|
+
- spec/dry/plain_type_constraint_spec.rb
|
109
113
|
- spec/dry/reader_spec.rb
|
110
114
|
- spec/dry/repetitive_definitions_spec.rb
|
111
115
|
- spec/dry/subclassing_spec.rb
|
116
|
+
- spec/dry/value_coercion_via_dry_types_spec.rb
|
112
117
|
- spec/spec_helper.rb
|
113
118
|
homepage: https://github.com/dryrb/dry-initializer
|
114
119
|
licenses:
|
@@ -130,7 +135,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
130
135
|
version: '0'
|
131
136
|
requirements: []
|
132
137
|
rubyforge_project:
|
133
|
-
rubygems_version: 2.
|
138
|
+
rubygems_version: 2.6.4
|
134
139
|
signing_key:
|
135
140
|
specification_version: 4
|
136
141
|
summary: DSL for declaring params and options of the initializer
|
@@ -139,14 +144,13 @@ test_files:
|
|
139
144
|
- spec/dry/container_spec.rb
|
140
145
|
- spec/dry/default_nil_spec.rb
|
141
146
|
- spec/dry/default_values_spec.rb
|
142
|
-
- spec/dry/
|
147
|
+
- spec/dry/dry_type_constraint_spec.rb
|
143
148
|
- spec/dry/invalid_default_spec.rb
|
144
|
-
- spec/dry/invalid_type_spec.rb
|
145
149
|
- spec/dry/missed_default_spec.rb
|
146
|
-
- spec/dry/
|
147
|
-
- spec/dry/
|
150
|
+
- spec/dry/object_type_constraint_spec.rb
|
151
|
+
- spec/dry/plain_type_constraint_spec.rb
|
148
152
|
- spec/dry/reader_spec.rb
|
149
153
|
- spec/dry/repetitive_definitions_spec.rb
|
150
154
|
- spec/dry/subclassing_spec.rb
|
155
|
+
- spec/dry/value_coercion_via_dry_types_spec.rb
|
151
156
|
- spec/spec_helper.rb
|
152
|
-
has_rdoc:
|
@@ -1,96 +0,0 @@
|
|
1
|
-
module Dry::Initializer
|
2
|
-
# A simple structure describes an argument (either param, or option)
|
3
|
-
#
|
4
|
-
# @api private
|
5
|
-
#
|
6
|
-
class Argument
|
7
|
-
include Errors
|
8
|
-
|
9
|
-
UNDEFINED = Object.new.freeze
|
10
|
-
|
11
|
-
# @!attribute [r] option
|
12
|
-
# @return [Boolean]
|
13
|
-
# Whether this is an option, or param of the initializer
|
14
|
-
attr_reader :option
|
15
|
-
|
16
|
-
# @!attribute [r] name
|
17
|
-
# @return [Symbol] the name of the argument
|
18
|
-
attr_reader :name
|
19
|
-
|
20
|
-
# @!attribute [r] default
|
21
|
-
# @return [Boolean] whether the argument has a default value
|
22
|
-
attr_reader :default
|
23
|
-
|
24
|
-
# @!attribute [r] default_value
|
25
|
-
# @return [Object] the default value of the argument
|
26
|
-
attr_reader :default_value
|
27
|
-
|
28
|
-
# @!attribute [r] type
|
29
|
-
# @return [Class, nil] a type constraint
|
30
|
-
attr_reader :type
|
31
|
-
|
32
|
-
# @!attribute [r] reader
|
33
|
-
# @return [Boolean] whether an attribute reader is defined for the argument
|
34
|
-
attr_reader :reader
|
35
|
-
|
36
|
-
def initialize(name, option:, reader: true, **options)
|
37
|
-
@name = name.to_sym
|
38
|
-
@option = option
|
39
|
-
@reader = reader
|
40
|
-
assign_default_value(options)
|
41
|
-
assign_type(options)
|
42
|
-
end
|
43
|
-
|
44
|
-
def ==(other)
|
45
|
-
other.name == name
|
46
|
-
end
|
47
|
-
|
48
|
-
def signature
|
49
|
-
case [option, default]
|
50
|
-
when [false, false] then name
|
51
|
-
when [false, true] then "#{name} = Dry::Initializer::Argument::UNDEFINED"
|
52
|
-
when [true, false] then "#{name}:"
|
53
|
-
else
|
54
|
-
"#{name}: Dry::Initializer::Argument::UNDEFINED"
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
def assignment
|
59
|
-
"@#{name} = #{name}"
|
60
|
-
end
|
61
|
-
|
62
|
-
def default_assignment
|
63
|
-
"@#{name} = instance_eval(&__arguments__[:#{name}].default_value)" \
|
64
|
-
" if #{name} == Dry::Initializer::Argument::UNDEFINED"
|
65
|
-
end
|
66
|
-
|
67
|
-
def type_constraint
|
68
|
-
"__arguments__[:#{name}].type.call(@#{name})"
|
69
|
-
end
|
70
|
-
|
71
|
-
private
|
72
|
-
|
73
|
-
def assign_default_value(options)
|
74
|
-
@default = options.key? :default
|
75
|
-
return unless @default
|
76
|
-
|
77
|
-
@default_value = options[:default]
|
78
|
-
return if Proc === @default_value
|
79
|
-
|
80
|
-
fail InvalidDefaultValueError.new(@default_value)
|
81
|
-
end
|
82
|
-
|
83
|
-
def assign_type(options)
|
84
|
-
return unless options.key? :type
|
85
|
-
|
86
|
-
type = options[:type]
|
87
|
-
type = plain_type_to_proc(type) if Module === type
|
88
|
-
fail InvalidTypeError.new(type) unless type.respond_to? :call
|
89
|
-
@type = type
|
90
|
-
end
|
91
|
-
|
92
|
-
def plain_type_to_proc(type)
|
93
|
-
proc { |value| fail TypeError.new(type, value) unless type === value }
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
@@ -1,85 +0,0 @@
|
|
1
|
-
module Dry::Initializer
|
2
|
-
# Collection of definitions for arguments
|
3
|
-
#
|
4
|
-
# @api private
|
5
|
-
#
|
6
|
-
class Arguments
|
7
|
-
include Errors
|
8
|
-
include Enumerable
|
9
|
-
|
10
|
-
def initialize(**arguments)
|
11
|
-
@arguments = arguments
|
12
|
-
end
|
13
|
-
|
14
|
-
def add(name, options)
|
15
|
-
validate_uniqueness(name)
|
16
|
-
validate_presence_of_default(name, options)
|
17
|
-
|
18
|
-
new_argument = Argument.new(name, options)
|
19
|
-
self.class.new @arguments.merge(name.to_sym => new_argument)
|
20
|
-
end
|
21
|
-
|
22
|
-
def declaration
|
23
|
-
<<-RUBY
|
24
|
-
attr_reader #{select(&:reader).map { |arg| ":#{arg.name}" }.join(", ")}
|
25
|
-
define_method :initialize do |#{signature}|
|
26
|
-
#{assign_arguments}
|
27
|
-
#{take_declarations}
|
28
|
-
#{assign_defaults}
|
29
|
-
#{check_constraints}
|
30
|
-
end
|
31
|
-
RUBY
|
32
|
-
end
|
33
|
-
|
34
|
-
def [](name)
|
35
|
-
@arguments[name]
|
36
|
-
end
|
37
|
-
|
38
|
-
private
|
39
|
-
|
40
|
-
def each
|
41
|
-
@arguments.each { |_, argument| yield(argument) }
|
42
|
-
end
|
43
|
-
|
44
|
-
def params
|
45
|
-
reject(&:option)
|
46
|
-
end
|
47
|
-
|
48
|
-
def options
|
49
|
-
select(&:option)
|
50
|
-
end
|
51
|
-
|
52
|
-
def validate_uniqueness(name)
|
53
|
-
fail ExistingArgumentError.new(name) if self[name.to_sym]
|
54
|
-
end
|
55
|
-
|
56
|
-
def validate_presence_of_default(name, options)
|
57
|
-
return if options.key? :default
|
58
|
-
return if options[:option]
|
59
|
-
return unless params.any?(&:default)
|
60
|
-
|
61
|
-
fail MissedDefaultValueError.new(name)
|
62
|
-
end
|
63
|
-
|
64
|
-
def signature
|
65
|
-
(params + options).map(&:signature).join(", ")
|
66
|
-
end
|
67
|
-
|
68
|
-
def assign_arguments
|
69
|
-
map(&:assignment).join("\n")
|
70
|
-
end
|
71
|
-
|
72
|
-
def take_declarations
|
73
|
-
return unless any?(&:default) || any?(&:type)
|
74
|
-
"__arguments__ = self.class.send(:arguments_builder).arguments"
|
75
|
-
end
|
76
|
-
|
77
|
-
def assign_defaults
|
78
|
-
select(&:default).map(&:default_assignment).join("\n")
|
79
|
-
end
|
80
|
-
|
81
|
-
def check_constraints
|
82
|
-
select(&:type).map(&:type_constraint).join("\n")
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|