dry-initializer 0.11.0 → 1.1.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/.gitignore +1 -0
- data/.rubocop.yml +4 -61
- data/.travis.yml +18 -11
- data/CHANGELOG.md +108 -43
- data/Gemfile +1 -0
- data/Rakefile +6 -0
- data/benchmarks/options.rb +4 -4
- data/benchmarks/params.rb +1 -1
- data/benchmarks/profiler.rb +28 -0
- data/benchmarks/with_types.rb +5 -9
- data/benchmarks/with_types_and_defaults.rb +2 -4
- data/benchmarks/without_options.rb +3 -3
- data/dry-initializer.gemspec +1 -1
- data/lib/dry/initializer/attribute.rb +92 -0
- data/lib/dry/initializer/builder.rb +76 -72
- data/lib/dry/initializer/exceptions/default_value_error.rb +8 -0
- data/lib/dry/initializer/exceptions/params_order_error.rb +8 -0
- data/lib/dry/initializer/exceptions/type_constraint_error.rb +7 -0
- data/lib/dry/initializer/option.rb +62 -0
- data/lib/dry/initializer/param.rb +54 -0
- data/lib/dry/initializer.rb +77 -13
- data/spec/enhancement_spec.rb +18 -0
- data/spec/missed_default_spec.rb +2 -2
- data/spec/optional_spec.rb +16 -6
- data/spec/options_var_spec.rb +39 -0
- data/spec/repetitive_definitions_spec.rb +38 -18
- data/spec/several_assignments_spec.rb +41 -0
- data/spec/type_constraint_spec.rb +6 -5
- metadata +15 -20
- data/lib/dry/initializer/errors/default_value_error.rb +0 -6
- data/lib/dry/initializer/errors/order_error.rb +0 -7
- data/lib/dry/initializer/errors/plugin_error.rb +0 -6
- data/lib/dry/initializer/errors/redefinition_error.rb +0 -5
- data/lib/dry/initializer/errors/type_constraint_error.rb +0 -5
- data/lib/dry/initializer/errors.rb +0 -10
- data/lib/dry/initializer/mixin.rb +0 -77
- data/lib/dry/initializer/plugins/base.rb +0 -47
- data/lib/dry/initializer/plugins/default_proc.rb +0 -28
- data/lib/dry/initializer/plugins/signature.rb +0 -28
- data/lib/dry/initializer/plugins/type_constraint.rb +0 -21
- data/lib/dry/initializer/plugins/variable_setter.rb +0 -30
- data/lib/dry/initializer/plugins.rb +0 -10
- data/lib/dry/initializer/signature.rb +0 -61
- data/spec/plugin_registry_spec.rb +0 -45
- data/spec/renaming_options_spec.rb +0 -20
@@ -5,7 +5,7 @@ describe "type constraint" do
|
|
5
5
|
before do
|
6
6
|
class Test::Foo
|
7
7
|
extend Dry::Initializer::Mixin
|
8
|
-
param :foo,
|
8
|
+
param :foo, Dry::Types["strict.string"], optional: true
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
@@ -28,20 +28,21 @@ describe "type constraint" do
|
|
28
28
|
context "if optional value not set" do
|
29
29
|
subject { Test::Foo.new }
|
30
30
|
|
31
|
-
it "
|
32
|
-
expect
|
31
|
+
it "not applicable to Dry::Initializer::UNDEFINED" do
|
32
|
+
expect(subject.instance_variable_get(:@foo))
|
33
|
+
.to eq Dry::Initializer::UNDEFINED
|
33
34
|
end
|
34
35
|
end
|
35
36
|
end
|
36
37
|
|
37
38
|
context "by invalid constraint" do
|
38
39
|
it "raises TypeError" do
|
39
|
-
expect
|
40
|
+
expect do
|
40
41
|
class Test::Foo
|
41
42
|
extend Dry::Initializer::Mixin
|
42
43
|
param :foo, type: String
|
43
44
|
end
|
44
|
-
|
45
|
+
end.to raise_error(TypeError)
|
45
46
|
end
|
46
47
|
end
|
47
48
|
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: 1.1.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: 2017-01-
|
12
|
+
date: 2017-01-28 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
@@ -91,6 +91,7 @@ files:
|
|
91
91
|
- benchmarks/options.rb
|
92
92
|
- benchmarks/params.rb
|
93
93
|
- benchmarks/params_vs_options.rb
|
94
|
+
- benchmarks/profiler.rb
|
94
95
|
- benchmarks/several_defaults.rb
|
95
96
|
- benchmarks/with_defaults.rb
|
96
97
|
- benchmarks/with_types.rb
|
@@ -99,34 +100,27 @@ files:
|
|
99
100
|
- dry-initializer.gemspec
|
100
101
|
- lib/dry-initializer.rb
|
101
102
|
- lib/dry/initializer.rb
|
103
|
+
- lib/dry/initializer/attribute.rb
|
102
104
|
- lib/dry/initializer/builder.rb
|
103
|
-
- lib/dry/initializer/
|
104
|
-
- lib/dry/initializer/
|
105
|
-
- lib/dry/initializer/
|
106
|
-
- lib/dry/initializer/
|
107
|
-
- lib/dry/initializer/
|
108
|
-
- lib/dry/initializer/errors/type_constraint_error.rb
|
109
|
-
- lib/dry/initializer/mixin.rb
|
110
|
-
- lib/dry/initializer/plugins.rb
|
111
|
-
- lib/dry/initializer/plugins/base.rb
|
112
|
-
- lib/dry/initializer/plugins/default_proc.rb
|
113
|
-
- lib/dry/initializer/plugins/signature.rb
|
114
|
-
- lib/dry/initializer/plugins/type_constraint.rb
|
115
|
-
- lib/dry/initializer/plugins/variable_setter.rb
|
116
|
-
- lib/dry/initializer/signature.rb
|
105
|
+
- lib/dry/initializer/exceptions/default_value_error.rb
|
106
|
+
- lib/dry/initializer/exceptions/params_order_error.rb
|
107
|
+
- lib/dry/initializer/exceptions/type_constraint_error.rb
|
108
|
+
- lib/dry/initializer/option.rb
|
109
|
+
- lib/dry/initializer/param.rb
|
117
110
|
- spec/base_spec.rb
|
118
111
|
- spec/container_spec.rb
|
119
112
|
- spec/custom_initializer_spec.rb
|
120
113
|
- spec/default_nil_spec.rb
|
121
114
|
- spec/default_values_spec.rb
|
115
|
+
- spec/enhancement_spec.rb
|
122
116
|
- spec/invalid_default_spec.rb
|
123
117
|
- spec/missed_default_spec.rb
|
124
118
|
- spec/optional_spec.rb
|
125
119
|
- spec/options_tolerance_spec.rb
|
126
|
-
- spec/
|
120
|
+
- spec/options_var_spec.rb
|
127
121
|
- spec/reader_spec.rb
|
128
|
-
- spec/renaming_options_spec.rb
|
129
122
|
- spec/repetitive_definitions_spec.rb
|
123
|
+
- spec/several_assignments_spec.rb
|
130
124
|
- spec/spec_helper.rb
|
131
125
|
- spec/subclassing_spec.rb
|
132
126
|
- spec/type_argument_spec.rb
|
@@ -162,14 +156,15 @@ test_files:
|
|
162
156
|
- spec/custom_initializer_spec.rb
|
163
157
|
- spec/default_nil_spec.rb
|
164
158
|
- spec/default_values_spec.rb
|
159
|
+
- spec/enhancement_spec.rb
|
165
160
|
- spec/invalid_default_spec.rb
|
166
161
|
- spec/missed_default_spec.rb
|
167
162
|
- spec/optional_spec.rb
|
168
163
|
- spec/options_tolerance_spec.rb
|
169
|
-
- spec/
|
164
|
+
- spec/options_var_spec.rb
|
170
165
|
- spec/reader_spec.rb
|
171
|
-
- spec/renaming_options_spec.rb
|
172
166
|
- spec/repetitive_definitions_spec.rb
|
167
|
+
- spec/several_assignments_spec.rb
|
173
168
|
- spec/spec_helper.rb
|
174
169
|
- spec/subclassing_spec.rb
|
175
170
|
- spec/type_argument_spec.rb
|
@@ -1,7 +0,0 @@
|
|
1
|
-
class Dry::Initializer::Errors::OrderError < SyntaxError
|
2
|
-
def initialize(name)
|
3
|
-
super "Cannot define the required param '#{name}' after optional ones." \
|
4
|
-
" Either provide a default value for the '#{name}', or declare it" \
|
5
|
-
" before params with default values."
|
6
|
-
end
|
7
|
-
end
|
@@ -1,10 +0,0 @@
|
|
1
|
-
module Dry::Initializer
|
2
|
-
# Collection of gem-specific exceptions
|
3
|
-
module Errors
|
4
|
-
require_relative "errors/default_value_error"
|
5
|
-
require_relative "errors/order_error"
|
6
|
-
require_relative "errors/plugin_error"
|
7
|
-
require_relative "errors/redefinition_error"
|
8
|
-
require_relative "errors/type_constraint_error"
|
9
|
-
end
|
10
|
-
end
|
@@ -1,77 +0,0 @@
|
|
1
|
-
module Dry::Initializer
|
2
|
-
# Class-level DSL for the initializer
|
3
|
-
module Mixin
|
4
|
-
# Declares a plain argument
|
5
|
-
#
|
6
|
-
# @param [#to_sym] name
|
7
|
-
#
|
8
|
-
# @option options [Object] :default The default value
|
9
|
-
# @option options [#call] :type The type constraings via `dry-types`
|
10
|
-
# @option options [Boolean] :reader (true) Whether to define attr_reader
|
11
|
-
#
|
12
|
-
# @return [self] itself
|
13
|
-
#
|
14
|
-
def param(name, type = nil, **options)
|
15
|
-
options[:type] = type if type
|
16
|
-
options[:option] = false
|
17
|
-
@__initializer_builder__ = __initializer_builder__.define(name, **options)
|
18
|
-
__initializer_builder__.call(__initializer_mixin__)
|
19
|
-
end
|
20
|
-
|
21
|
-
# Declares a named argument
|
22
|
-
#
|
23
|
-
# @param (see #param)
|
24
|
-
# @option (see #param)
|
25
|
-
# @return (see #param)
|
26
|
-
#
|
27
|
-
def option(name, type = nil, **options)
|
28
|
-
options[:type] = type if type
|
29
|
-
options[:option] = true
|
30
|
-
@__initializer_builder__ = __initializer_builder__.define(name, **options)
|
31
|
-
__initializer_builder__.call(__initializer_mixin__)
|
32
|
-
end
|
33
|
-
|
34
|
-
# Adds new plugin to the builder
|
35
|
-
#
|
36
|
-
# @param [Dry::Initializer::Plugins::Base] plugin
|
37
|
-
# @return [self] itself
|
38
|
-
#
|
39
|
-
def register_initializer_plugin(plugin)
|
40
|
-
@__initializer_builder__ = __initializer_builder__.register(plugin)
|
41
|
-
__initializer_builder__.call(__initializer_mixin__)
|
42
|
-
end
|
43
|
-
|
44
|
-
private
|
45
|
-
|
46
|
-
def __initializer_mixin__
|
47
|
-
@__initializer_mixin__ ||= Module.new do
|
48
|
-
def initialize(*args)
|
49
|
-
__initialize__(*args)
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def __initializer_builder__
|
55
|
-
@__initializer_builder__ ||= Builder.new
|
56
|
-
end
|
57
|
-
|
58
|
-
def inherited(klass)
|
59
|
-
new_builder = __initializer_builder__.dup
|
60
|
-
klass.instance_variable_set :@__initializer_builder__, new_builder
|
61
|
-
|
62
|
-
new_mixin = Module.new
|
63
|
-
new_builder.call(new_mixin)
|
64
|
-
klass.instance_variable_set :@__initializer_mixin__, new_mixin
|
65
|
-
klass.include new_mixin
|
66
|
-
|
67
|
-
super
|
68
|
-
end
|
69
|
-
|
70
|
-
def self.extended(klass)
|
71
|
-
super
|
72
|
-
mixin = klass.send(:__initializer_mixin__)
|
73
|
-
klass.send(:__initializer_builder__).call(mixin)
|
74
|
-
klass.include mixin
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
@@ -1,47 +0,0 @@
|
|
1
|
-
module Dry::Initializer::Plugins
|
2
|
-
# Base class for plugins
|
3
|
-
#
|
4
|
-
# A plugin should has class method [.call] that takes argument name and
|
5
|
-
# settings and return a chunk of code for the #initialize method body.
|
6
|
-
#
|
7
|
-
class Base
|
8
|
-
include Dry::Initializer::Errors
|
9
|
-
|
10
|
-
# Builds the proc for the `__after_initializer__` callback
|
11
|
-
#
|
12
|
-
# @param [#to_s] name
|
13
|
-
# @param [Hash<Symbol, Object>] settings
|
14
|
-
#
|
15
|
-
# @return [String, Proc, nil]
|
16
|
-
#
|
17
|
-
def self.call(name, settings)
|
18
|
-
new(name, settings).call
|
19
|
-
end
|
20
|
-
|
21
|
-
# @private
|
22
|
-
attr_reader :name, :settings
|
23
|
-
|
24
|
-
# Initializes a builder with argument name and settings
|
25
|
-
# @param (see .call)
|
26
|
-
def initialize(name, settings)
|
27
|
-
@name = name
|
28
|
-
@settings = settings
|
29
|
-
end
|
30
|
-
|
31
|
-
# Checks equality to another instance by name
|
32
|
-
# @return [Boolean]
|
33
|
-
def ==(other)
|
34
|
-
other.instance_of?(self.class) && (other.name == name)
|
35
|
-
end
|
36
|
-
|
37
|
-
# Builds a chunk of code
|
38
|
-
# @return (see .call)
|
39
|
-
def call; end
|
40
|
-
|
41
|
-
# Returns the name for the attribute
|
42
|
-
# @return (see .name)
|
43
|
-
def rename
|
44
|
-
@rename ||= settings[:option] ? (settings[:as] || name) : name
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
@@ -1,28 +0,0 @@
|
|
1
|
-
module Dry::Initializer::Plugins
|
2
|
-
# Builds a block to be evaluated by initializer (__after_initialize__)
|
3
|
-
# to assign a default value to the argument
|
4
|
-
class DefaultProc < Base
|
5
|
-
def call
|
6
|
-
return unless default
|
7
|
-
|
8
|
-
ivar = :"@#{rename}"
|
9
|
-
default_proc = default
|
10
|
-
|
11
|
-
proc do
|
12
|
-
if instance_variable_get(ivar) == Dry::Initializer::UNDEFINED
|
13
|
-
instance_variable_set ivar, instance_eval(&default_proc)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
private
|
19
|
-
|
20
|
-
def default
|
21
|
-
return unless settings.key? :default
|
22
|
-
|
23
|
-
@default ||= settings[:default].tap do |value|
|
24
|
-
fail DefaultValueError.new(name, value) unless Proc === value
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
@@ -1,28 +0,0 @@
|
|
1
|
-
module Dry::Initializer::Plugins
|
2
|
-
# Plugin builds a chunk of code for the initializer's signature:
|
3
|
-
#
|
4
|
-
# @example
|
5
|
-
# Signature.call(:user)
|
6
|
-
# # => "user"
|
7
|
-
#
|
8
|
-
# Signature.call(:user, default: -> { nil })
|
9
|
-
# # => "user = Dry::Initializer::UNDEFINED"
|
10
|
-
#
|
11
|
-
# Signature.call(:user, option: true)
|
12
|
-
# # => nil
|
13
|
-
#
|
14
|
-
class Signature < Base
|
15
|
-
def param?
|
16
|
-
settings[:option] != true
|
17
|
-
end
|
18
|
-
|
19
|
-
def required?
|
20
|
-
!settings.key?(:default) && !settings[:optional]
|
21
|
-
end
|
22
|
-
|
23
|
-
def call
|
24
|
-
return unless param?
|
25
|
-
required? ? name.to_s : "#{name} = Dry::Initializer::UNDEFINED"
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
@@ -1,21 +0,0 @@
|
|
1
|
-
module Dry::Initializer::Plugins
|
2
|
-
# Plugin builds either chunk of code for the #initializer,
|
3
|
-
# or a proc for the ##__after_initialize__ callback.
|
4
|
-
class TypeConstraint < Base
|
5
|
-
def call
|
6
|
-
return unless settings.key? :type
|
7
|
-
|
8
|
-
type = settings[:type]
|
9
|
-
fail TypeConstraintError.new(rename, type) unless type.respond_to? :call
|
10
|
-
|
11
|
-
ivar = :"@#{rename}"
|
12
|
-
lambda do |*|
|
13
|
-
value = instance_variable_get(ivar)
|
14
|
-
|
15
|
-
if value != Dry::Initializer::UNDEFINED
|
16
|
-
instance_variable_set ivar, type.call(value)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
@@ -1,30 +0,0 @@
|
|
1
|
-
module Dry::Initializer::Plugins
|
2
|
-
# Plugin builds a code for variable setter:
|
3
|
-
#
|
4
|
-
# @example
|
5
|
-
# VariableSetter.call(:user, option: false)
|
6
|
-
# # => "@user = user"
|
7
|
-
#
|
8
|
-
# VariableSetter.call(:user, option: true)
|
9
|
-
# # => "@user = __options__.fetch(:user)"
|
10
|
-
#
|
11
|
-
# VariableSetter.call(:user, option: true, optional: true)
|
12
|
-
# # => "@user = __options__.fetch(:user, Dry::Initializer::UNDEFINED)"
|
13
|
-
#
|
14
|
-
class VariableSetter < Base
|
15
|
-
def param?
|
16
|
-
settings[:option] != true
|
17
|
-
end
|
18
|
-
|
19
|
-
def required?
|
20
|
-
!settings.key?(:default) && !settings[:optional]
|
21
|
-
end
|
22
|
-
|
23
|
-
def call
|
24
|
-
return "@#{name} = #{name}" if param?
|
25
|
-
key = ":\"#{name}\""
|
26
|
-
return "@#{rename} = __options__.fetch(#{key})" if required?
|
27
|
-
"@#{rename} = __options__.fetch(#{key}, Dry::Initializer::UNDEFINED)"
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
@@ -1,10 +0,0 @@
|
|
1
|
-
module Dry::Initializer
|
2
|
-
# Namespace for code plugins builders
|
3
|
-
module Plugins
|
4
|
-
require_relative "plugins/base"
|
5
|
-
require_relative "plugins/default_proc"
|
6
|
-
require_relative "plugins/signature"
|
7
|
-
require_relative "plugins/type_constraint"
|
8
|
-
require_relative "plugins/variable_setter"
|
9
|
-
end
|
10
|
-
end
|
@@ -1,61 +0,0 @@
|
|
1
|
-
module Dry::Initializer
|
2
|
-
# Immutable 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(*list)
|
9
|
-
@list = list
|
10
|
-
end
|
11
|
-
|
12
|
-
def add(*args)
|
13
|
-
signature = Plugins::Signature.new(*args)
|
14
|
-
|
15
|
-
validate_order_of signature
|
16
|
-
validate_param_uniqueness_of signature
|
17
|
-
validate_option_uniqueness_of signature
|
18
|
-
validate_attribute_uniqueness_of signature
|
19
|
-
|
20
|
-
self.class.new(*@list, signature)
|
21
|
-
end
|
22
|
-
|
23
|
-
def each
|
24
|
-
@list.each { |item| yield item }
|
25
|
-
end
|
26
|
-
|
27
|
-
def call
|
28
|
-
options = all?(&:param?) ? %w(__options__={}) : %w(**__options__)
|
29
|
-
(select(&:param?).map(&:call) + options).compact.join(", ")
|
30
|
-
end
|
31
|
-
|
32
|
-
private
|
33
|
-
|
34
|
-
def validate_param_uniqueness_of(signature)
|
35
|
-
return unless signature.param?
|
36
|
-
return unless select(&:param?).map(&:name).include? signature.name
|
37
|
-
|
38
|
-
fail RedefinitionError.new(signature.name)
|
39
|
-
end
|
40
|
-
|
41
|
-
def validate_option_uniqueness_of(signature)
|
42
|
-
return if signature.param?
|
43
|
-
return unless reject(&:param?).map(&:name).include? signature.name
|
44
|
-
|
45
|
-
fail RedefinitionError.new(signature.name)
|
46
|
-
end
|
47
|
-
|
48
|
-
def validate_attribute_uniqueness_of(signature)
|
49
|
-
return unless map(&:rename).include? signature.rename
|
50
|
-
|
51
|
-
fail RedefinitionError.new(signature.name)
|
52
|
-
end
|
53
|
-
|
54
|
-
def validate_order_of(signature)
|
55
|
-
return unless signature.required? && signature.param?
|
56
|
-
return unless reject(&:required?).any?(&:param?)
|
57
|
-
|
58
|
-
fail OrderError.new(signature.name)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|