dry-initializer 0.11.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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