dry-initializer 0.11.0 → 1.0.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.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +18 -11
  4. data/CHANGELOG.md +85 -43
  5. data/benchmarks/options.rb +4 -4
  6. data/benchmarks/with_types.rb +2 -4
  7. data/benchmarks/with_types_and_defaults.rb +2 -4
  8. data/dry-initializer.gemspec +1 -1
  9. data/lib/dry/initializer.rb +77 -13
  10. data/lib/dry/initializer/attribute.rb +52 -0
  11. data/lib/dry/initializer/builder.rb +79 -72
  12. data/lib/dry/initializer/exceptions/default_value_error.rb +8 -0
  13. data/lib/dry/initializer/exceptions/params_order_error.rb +8 -0
  14. data/lib/dry/initializer/exceptions/type_constraint_error.rb +7 -0
  15. data/lib/dry/initializer/option.rb +55 -0
  16. data/lib/dry/initializer/param.rb +49 -0
  17. data/spec/missed_default_spec.rb +2 -2
  18. data/spec/optional_spec.rb +16 -6
  19. data/spec/options_var_spec.rb +39 -0
  20. data/spec/repetitive_definitions_spec.rb +38 -18
  21. data/spec/type_constraint_spec.rb +3 -3
  22. metadata +10 -18
  23. data/lib/dry/initializer/errors.rb +0 -10
  24. data/lib/dry/initializer/errors/default_value_error.rb +0 -6
  25. data/lib/dry/initializer/errors/order_error.rb +0 -7
  26. data/lib/dry/initializer/errors/plugin_error.rb +0 -6
  27. data/lib/dry/initializer/errors/redefinition_error.rb +0 -5
  28. data/lib/dry/initializer/errors/type_constraint_error.rb +0 -5
  29. data/lib/dry/initializer/mixin.rb +0 -77
  30. data/lib/dry/initializer/plugins.rb +0 -10
  31. data/lib/dry/initializer/plugins/base.rb +0 -47
  32. data/lib/dry/initializer/plugins/default_proc.rb +0 -28
  33. data/lib/dry/initializer/plugins/signature.rb +0 -28
  34. data/lib/dry/initializer/plugins/type_constraint.rb +0 -21
  35. data/lib/dry/initializer/plugins/variable_setter.rb +0 -30
  36. data/lib/dry/initializer/signature.rb +0 -61
  37. data/spec/plugin_registry_spec.rb +0 -45
@@ -3,8 +3,8 @@ describe "missed default values" do
3
3
  class Test::Foo
4
4
  extend Dry::Initializer::Mixin
5
5
 
6
- param :foo, default: proc { :FOO }
7
- param :bar
6
+ param :foo, default: proc { :FOO }
7
+ param :bar, required: true
8
8
  end
9
9
  end
10
10
 
@@ -9,22 +9,27 @@ describe "optional value" do
9
9
  end
10
10
  end
11
11
 
12
- it "is left UNDEFINED by default" do
12
+ it "quacks like nil" do
13
13
  subject = Test::Foo.new(1)
14
14
 
15
- expect(subject.foo).to eq 1
16
- expect(subject.bar).to eq Dry::Initializer::UNDEFINED
15
+ expect(subject.bar).to eq nil
16
+ end
17
+
18
+ it "keeps info about been UNDEFINED" do
19
+ subject = Test::Foo.new(1)
20
+
21
+ expect(subject.instance_variable_get(:@bar))
22
+ .to eq Dry::Initializer::UNDEFINED
17
23
  end
18
24
 
19
25
  it "can be set explicitly" do
20
26
  subject = Test::Foo.new(1, "qux")
21
27
 
22
- expect(subject.foo).to eq 1
23
28
  expect(subject.bar).to eq "qux"
24
29
  end
25
30
  end
26
31
 
27
- context "when has default value" do
32
+ context "when has a default value" do
28
33
  before do
29
34
  class Test::Foo
30
35
  extend Dry::Initializer::Mixin
@@ -37,8 +42,13 @@ describe "optional value" do
37
42
  it "is takes default value" do
38
43
  subject = Test::Foo.new(1)
39
44
 
40
- expect(subject.foo).to eq 1
41
45
  expect(subject.bar).to eq "baz"
42
46
  end
47
+
48
+ it "can be set explicitly" do
49
+ subject = Test::Foo.new(1, "qux")
50
+
51
+ expect(subject.bar).to eq "qux"
52
+ end
43
53
  end
44
54
  end
@@ -0,0 +1,39 @@
1
+ describe "@__options__" do
2
+ context "when class has no options" do
3
+ before do
4
+ class Test::Foo
5
+ extend Dry::Initializer::Mixin
6
+ param :foo
7
+ end
8
+ end
9
+
10
+ it "is set to empty hash" do
11
+ subject = Test::Foo.new(1)
12
+
13
+ expect(subject.instance_variable_get(:@__options__)).to eq({})
14
+ end
15
+ end
16
+
17
+ context "when class has options" do
18
+ before do
19
+ class Test::Foo
20
+ extend Dry::Initializer::Mixin
21
+ param :foo
22
+ option :bar, optional: true
23
+ option :baz, optional: true
24
+ end
25
+ end
26
+
27
+ it "is set to empty hash if no options assigned" do
28
+ subject = Test::Foo.new(1)
29
+
30
+ expect(subject.instance_variable_get(:@__options__)).to eq({})
31
+ end
32
+
33
+ it "is set to hash of assigned options" do
34
+ subject = Test::Foo.new(1, baz: :QUX)
35
+
36
+ expect(subject.instance_variable_get(:@__options__)).to eq({ baz: :QUX })
37
+ end
38
+ end
39
+ end
@@ -1,49 +1,69 @@
1
1
  describe "repetitive definitions" do
2
+ subject { Test::Foo.new }
3
+
2
4
  context "of params" do
3
- subject do
5
+ before do
4
6
  class Test::Foo
5
7
  extend Dry::Initializer::Mixin
6
8
 
7
- param :foo
8
- param :bar
9
- param :foo
9
+ param :foo, default: proc { 0 }
10
+ param :bar, default: proc { 1 }
11
+ param :foo, default: proc { 2 }
10
12
  end
11
13
  end
12
14
 
13
- it "raise SyntaxError" do
14
- expect { subject }.to raise_error SyntaxError, /foo/
15
+ it "reloads the attribute" do
16
+ expect(subject.foo).to eq 2
15
17
  end
16
18
  end
17
19
 
18
20
  context "of options" do
19
- subject do
21
+ before do
20
22
  class Test::Foo
21
23
  extend Dry::Initializer::Mixin
22
24
 
23
- option :foo
24
- option :bar
25
- option :foo
25
+ option :foo, default: proc { 0 }
26
+ option :bar, default: proc { 1 }
27
+ option :foo, default: proc { 2 }
26
28
  end
27
29
  end
28
30
 
29
- it "raise SyntaxError" do
30
- expect { subject }.to raise_error SyntaxError, /foo/
31
+ it "reloads the attribute" do
32
+ expect(subject.foo).to eq 2
31
33
  end
32
34
  end
33
35
 
34
36
  context "of param and option" do
35
- subject do
37
+ before do
38
+ class Test::Foo
39
+ extend Dry::Initializer::Mixin
40
+
41
+ param :foo, default: proc { 0 }
42
+ option :bar, default: proc { 1 }
43
+ option :foo, default: proc { 2 }
44
+ end
45
+ end
46
+
47
+ it "reloads the attribute" do
48
+ expect(subject.foo).to eq 2
49
+ end
50
+ end
51
+
52
+ context "of optional param and option" do
53
+ before do
36
54
  class Test::Foo
37
55
  extend Dry::Initializer::Mixin
38
56
 
39
- param :foo
40
- option :bar
41
- option :foo
57
+ param :foo, optional: true
58
+ option :bar, optional: true
59
+ option :foo, optional: true
42
60
  end
43
61
  end
44
62
 
45
- it "raise SyntaxError" do
46
- expect { subject }.to raise_error SyntaxError, /foo/
63
+ it "allows various assignments" do
64
+ expect(Test::Foo.new(1).foo).to eq 1
65
+ expect(Test::Foo.new(foo: 2).foo).to eq 2
66
+ expect(Test::Foo.new(1, foo: 2).foo).to eq 2
47
67
  end
48
68
  end
49
69
  end
@@ -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, type: Dry::Types["strict.string"], optional: true
8
+ param :foo, Dry::Types["strict.string"], optional: true
9
9
  end
10
10
  end
11
11
 
@@ -28,8 +28,8 @@ describe "type constraint" do
28
28
  context "if optional value not set" do
29
29
  subject { Test::Foo.new }
30
30
 
31
- it "completes the initialization" do
32
- expect { subject }.not_to raise_error
31
+ it "applies type constraint to Dry::Initializer::UNDEFINED" do
32
+ expect { subject }.to raise_error Dry::Types::ConstraintError
33
33
  end
34
34
  end
35
35
  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.11.0
4
+ version: 1.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: 2017-01-02 00:00:00.000000000 Z
12
+ date: 2017-01-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
@@ -99,21 +99,13 @@ files:
99
99
  - dry-initializer.gemspec
100
100
  - lib/dry-initializer.rb
101
101
  - lib/dry/initializer.rb
102
+ - lib/dry/initializer/attribute.rb
102
103
  - lib/dry/initializer/builder.rb
103
- - lib/dry/initializer/errors.rb
104
- - lib/dry/initializer/errors/default_value_error.rb
105
- - lib/dry/initializer/errors/order_error.rb
106
- - lib/dry/initializer/errors/plugin_error.rb
107
- - lib/dry/initializer/errors/redefinition_error.rb
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
104
+ - lib/dry/initializer/exceptions/default_value_error.rb
105
+ - lib/dry/initializer/exceptions/params_order_error.rb
106
+ - lib/dry/initializer/exceptions/type_constraint_error.rb
107
+ - lib/dry/initializer/option.rb
108
+ - lib/dry/initializer/param.rb
117
109
  - spec/base_spec.rb
118
110
  - spec/container_spec.rb
119
111
  - spec/custom_initializer_spec.rb
@@ -123,7 +115,7 @@ files:
123
115
  - spec/missed_default_spec.rb
124
116
  - spec/optional_spec.rb
125
117
  - spec/options_tolerance_spec.rb
126
- - spec/plugin_registry_spec.rb
118
+ - spec/options_var_spec.rb
127
119
  - spec/reader_spec.rb
128
120
  - spec/renaming_options_spec.rb
129
121
  - spec/repetitive_definitions_spec.rb
@@ -166,7 +158,7 @@ test_files:
166
158
  - spec/missed_default_spec.rb
167
159
  - spec/optional_spec.rb
168
160
  - spec/options_tolerance_spec.rb
169
- - spec/plugin_registry_spec.rb
161
+ - spec/options_var_spec.rb
170
162
  - spec/reader_spec.rb
171
163
  - spec/renaming_options_spec.rb
172
164
  - spec/repetitive_definitions_spec.rb
@@ -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,6 +0,0 @@
1
- class Dry::Initializer::Errors::DefaultValueError < TypeError
2
- def initialize(name, value)
3
- super "Cannot set #{value.inspect} directly as a default value" \
4
- " of the argument '#{name}'. Wrap it to either proc or lambda."
5
- end
6
- end
@@ -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,6 +0,0 @@
1
- class Dry::Initializer::Errors::PluginError < TypeError
2
- def initialize(plugin)
3
- super "#{plugin} is not a valid plugin." \
4
- " Use a subclass of Dry::Initialier::Plugins::Base."
5
- end
6
- end
@@ -1,5 +0,0 @@
1
- class Dry::Initializer::Errors::RedefinitionError < SyntaxError
2
- def initialize(name)
3
- super "The argument '#{name}' is already defined."
4
- end
5
- end
@@ -1,5 +0,0 @@
1
- class Dry::Initializer::Errors::TypeConstraintError < TypeError
2
- def initialize(name, type)
3
- super "#{type} used as constraint for argument '#{name}' is not a dry-type."
4
- end
5
- 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,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,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