dry-initializer 3.0.4 → 3.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.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -0
  3. data/LICENSE +1 -1
  4. data/README.md +4 -3
  5. data/dry-initializer.gemspec +15 -13
  6. data/lib/dry/initializer/builders/attribute.rb +92 -82
  7. data/lib/dry/initializer/builders/initializer.rb +56 -54
  8. data/lib/dry/initializer/builders/reader.rb +55 -49
  9. data/lib/dry/initializer/builders/signature.rb +29 -23
  10. data/lib/dry/initializer/builders.rb +9 -5
  11. data/lib/dry/initializer/config.rb +160 -158
  12. data/lib/dry/initializer/definition.rb +58 -54
  13. data/lib/dry/initializer/dispatchers/build_nested_type.rb +54 -40
  14. data/lib/dry/initializer/dispatchers/check_type.rb +45 -39
  15. data/lib/dry/initializer/dispatchers/prepare_default.rb +32 -25
  16. data/lib/dry/initializer/dispatchers/prepare_ivar.rb +13 -6
  17. data/lib/dry/initializer/dispatchers/prepare_optional.rb +14 -7
  18. data/lib/dry/initializer/dispatchers/prepare_reader.rb +29 -22
  19. data/lib/dry/initializer/dispatchers/prepare_source.rb +12 -5
  20. data/lib/dry/initializer/dispatchers/prepare_target.rb +44 -37
  21. data/lib/dry/initializer/dispatchers/unwrap_type.rb +21 -10
  22. data/lib/dry/initializer/dispatchers/wrap_type.rb +24 -17
  23. data/lib/dry/initializer/dispatchers.rb +48 -43
  24. data/lib/dry/initializer/dsl.rb +42 -34
  25. data/lib/dry/initializer/errors.rb +22 -0
  26. data/lib/dry/initializer/mixin/local.rb +19 -13
  27. data/lib/dry/initializer/mixin/root.rb +12 -7
  28. data/lib/dry/initializer/mixin.rb +17 -12
  29. data/lib/dry/initializer/struct.rb +34 -29
  30. data/lib/dry/initializer/undefined.rb +7 -1
  31. data/lib/dry/initializer/version.rb +3 -1
  32. data/lib/dry/initializer.rb +12 -9
  33. data/lib/dry-initializer.rb +3 -1
  34. data/lib/tasks/benchmark.rake +15 -13
  35. data/lib/tasks/profile.rake +20 -16
  36. metadata +5 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2d1722e29cdab2ffcf349bc159451afb795aa399c91e0ebae2296318a5b3b166
4
- data.tar.gz: 4e6a589a9898e6701dcadbd321d78041da27e58f783bfbfa566d828134f6c081
3
+ metadata.gz: 49644712268c1c8896eb7b9d067d5f3abf65789330d465f0acad780a4f50644e
4
+ data.tar.gz: 102ef164a75b9d4849400753a21046d5753217806de6c8963476ef8fafeb780d
5
5
  SHA512:
6
- metadata.gz: 66596268197d4fc509eb9cc5dfd738af4d3d4f6c33a861cc4877328817d7a28155de3987c8df3b6fdc868bfec346a3e8dd67891f702ead9e47142c756ad306bf
7
- data.tar.gz: c4f91414ec4798759ed48b783974f922d598c01e613116c8fd077ed3c886a376c0ba260928ef3788ff0f7984cdc086cc03d3404052a97f2cb8c1658c7913cc69
6
+ metadata.gz: '07780a5de808586056b92a3b9a2f1169f5fea4d7879abd1080fc27a7e6123b22d2a07878e9ca9203995c9f01c3e5a47b030b5dc7004d67a4a540413aabdb5890'
7
+ data.tar.gz: e352bf6de1a4aae2cf183be62ef4f64a4c70daf0f329122b0d6cd00a7e6081767aa745e938ae4464e52d322bfb08ce943a3312b4f92e02d87c1b968edf0498c4
data/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ <!--- DO NOT EDIT THIS FILE - IT'S AUTOMATICALLY GENERATED VIA DEVTOOLS --->
2
+
3
+ ## 3.1.0 2022-01-16
4
+
5
+
6
+ ### Changed
7
+
8
+ - Improved error messages on type mismatch (@swerling)
9
+ - [BREAKING] Minimal supported Ruby version is 2.7 (@flash-gordon)
10
+
11
+ [Compare v3.0.4...v3.1.0](https://github.com/dry-rb/dry-initializer/compare/v3.0.4...v3.1.0)
12
+
1
13
  ## 3.0.4 2020-09-29
2
14
 
3
15
 
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2015-2020 dry-rb team
3
+ Copyright (c) 2015-2021 dry-rb team
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy of
6
6
  this software and associated documentation files (the "Software"), to deal in
data/README.md CHANGED
@@ -1,3 +1,4 @@
1
+ <!--- this file is synced from dry-rb/template-gem project -->
1
2
  [gem]: https://rubygems.org/gems/dry-initializer
2
3
  [actions]: https://github.com/dry-rb/dry-initializer/actions
3
4
  [codacy]: https://www.codacy.com/gh/dry-rb/dry-initializer
@@ -14,15 +15,15 @@
14
15
 
15
16
  ## Links
16
17
 
17
- * [User documentation](http://dry-rb.org/gems/dry-initializer)
18
+ * [User documentation](https://dry-rb.org/gems/dry-initializer)
18
19
  * [API documentation](http://rubydoc.info/gems/dry-initializer)
19
20
 
20
21
  ## Supported Ruby versions
21
22
 
22
23
  This library officially supports the following Ruby versions:
23
24
 
24
- * MRI >= `2.4`
25
- * jruby >= `9.2`
25
+ * MRI `>= 2.7.0`
26
+ * jruby `>= 9.3` (postponed until 2.7 is supported)
26
27
 
27
28
  ## License
28
29
 
@@ -1,33 +1,35 @@
1
1
  # frozen_string_literal: true
2
- # this file is managed by dry-rb/devtools project
3
2
 
4
- lib = File.expand_path('lib', __dir__)
3
+ # this file is synced from dry-rb/template-gem project
4
+
5
+ lib = File.expand_path("lib", __dir__)
5
6
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
6
- require 'dry/initializer/version'
7
+ require "dry/initializer/version"
7
8
 
8
9
  Gem::Specification.new do |spec|
9
- spec.name = 'dry-initializer'
10
+ spec.name = "dry-initializer"
10
11
  spec.authors = ["Vladimir Kochnev (marshall-lee)", "Andrew Kozin (nepalez)"]
11
12
  spec.email = ["andrew.kozin@gmail.com"]
12
- spec.license = 'MIT'
13
+ spec.license = "MIT"
13
14
  spec.version = Dry::Initializer::VERSION.dup
14
15
 
15
16
  spec.summary = "DSL for declaring params and options of the initializer"
16
17
  spec.description = spec.summary
17
- spec.homepage = 'https://dry-rb.org/gems/dry-initializer'
18
+ spec.homepage = "https://dry-rb.org/gems/dry-initializer"
18
19
  spec.files = Dir["CHANGELOG.md", "LICENSE", "README.md", "dry-initializer.gemspec", "lib/**/*"]
19
- spec.bindir = 'bin'
20
+ spec.bindir = "bin"
20
21
  spec.executables = []
21
- spec.require_paths = ['lib']
22
+ spec.require_paths = ["lib"]
22
23
 
23
- spec.metadata['allowed_push_host'] = 'https://rubygems.org'
24
- spec.metadata['changelog_uri'] = 'https://github.com/dry-rb/dry-initializer/blob/master/CHANGELOG.md'
25
- spec.metadata['source_code_uri'] = 'https://github.com/dry-rb/dry-initializer'
26
- spec.metadata['bug_tracker_uri'] = 'https://github.com/dry-rb/dry-initializer/issues'
24
+ spec.metadata["allowed_push_host"] = "https://rubygems.org"
25
+ spec.metadata["changelog_uri"] = "https://github.com/dry-rb/dry-initializer/blob/master/CHANGELOG.md"
26
+ spec.metadata["source_code_uri"] = "https://github.com/dry-rb/dry-initializer"
27
+ spec.metadata["bug_tracker_uri"] = "https://github.com/dry-rb/dry-initializer/issues"
27
28
 
28
- spec.required_ruby_version = ">= 2.4.0"
29
+ spec.required_ruby_version = ">= 2.7.0"
29
30
 
30
31
  # to update dependencies edit project.yml
32
+
31
33
  spec.add_development_dependency "rake"
32
34
  spec.add_development_dependency "rspec"
33
35
  end
@@ -1,86 +1,96 @@
1
- module Dry::Initializer::Builders
2
- # @private
3
- class Attribute
4
- def self.[](definition)
5
- new(definition).call
6
- end
7
-
8
- def call
9
- lines.compact
10
- end
11
-
12
- private
13
-
14
- # rubocop: disable Metrics/MethodLength
15
- def initialize(definition)
16
- @definition = definition
17
- @option = definition.option
18
- @type = definition.type
19
- @optional = definition.optional
20
- @default = definition.default
21
- @source = definition.source
22
- @ivar = definition.ivar
23
- @null = definition.null ? 'Dry::Initializer::UNDEFINED' : 'nil'
24
- @opts = '__dry_initializer_options__'
25
- @congif = '__dry_initializer_config__'
26
- @item = '__dry_initializer_definition__'
27
- @val = @option ? '__dry_initializer_value__' : @source
28
- end
29
- # rubocop: enable Metrics/MethodLength
30
-
31
- def lines
32
- [
33
- '',
34
- definition_line,
35
- reader_line,
36
- default_line,
37
- coercion_line,
38
- assignment_line
39
- ]
40
- end
41
-
42
- def reader_line
43
- return unless @option
44
-
45
- @optional ? optional_reader : required_reader
46
- end
47
-
48
- def optional_reader
49
- "#{@val} = #{@opts}.fetch(:'#{@source}', #{@null})"
50
- end
51
-
52
- def required_reader
53
- "#{@val} = #{@opts}.fetch(:'#{@source}')" \
54
- " { raise KeyError, \"\#{self.class}: #{@definition} is required\" }"
55
- end
56
-
57
- def definition_line
58
- return unless @type || @default
59
-
60
- "#{@item} = __dry_initializer_config__.definitions[:'#{@source}']"
61
- end
62
-
63
- def default_line
64
- return unless @default
65
-
66
- "#{@val} = instance_exec(&#{@item}.default) if #{@null} == #{@val}"
67
- end
68
-
69
- def coercion_line
70
- return unless @type
71
-
72
- arity = @type.is_a?(Proc) ? @type.arity : @type.method(:call).arity
73
-
74
- if arity.equal?(1) || arity.negative?
75
- "#{@val} = #{@item}.type.call(#{@val}) unless #{@null} == #{@val}"
76
- else
77
- "#{@val} = #{@item}.type.call(#{@val}, self) unless #{@null} == #{@val}"
1
+ # frozen_string_literal: true
2
+
3
+ module Dry
4
+ module Initializer
5
+ module Builders
6
+ # @private
7
+ class Attribute
8
+ def self.[](definition)
9
+ new(definition).call
10
+ end
11
+
12
+ def call
13
+ lines.compact
14
+ end
15
+
16
+ private
17
+
18
+ def initialize(definition)
19
+ @definition = definition
20
+ @option = definition.option
21
+ @type = definition.type
22
+ @optional = definition.optional
23
+ @default = definition.default
24
+ @source = definition.source
25
+ @ivar = definition.ivar
26
+ @null = definition.null ? "Dry::Initializer::UNDEFINED" : "nil"
27
+ @opts = "__dry_initializer_options__"
28
+ @congif = "__dry_initializer_config__"
29
+ @item = "__dry_initializer_definition__"
30
+ @val = @option ? "__dry_initializer_value__" : @source
31
+ end
32
+
33
+ def lines
34
+ [
35
+ "",
36
+ definition_line,
37
+ reader_line,
38
+ default_line,
39
+ coercion_line,
40
+ assignment_line
41
+ ]
42
+ end
43
+
44
+ def reader_line
45
+ return unless @option
46
+
47
+ @optional ? optional_reader : required_reader
48
+ end
49
+
50
+ def optional_reader
51
+ "#{@val} = #{@opts}.fetch(:'#{@source}', #{@null})"
52
+ end
53
+
54
+ def required_reader
55
+ "#{@val} = #{@opts}.fetch(:'#{@source}')" \
56
+ " { raise KeyError, \"\#{self.class}: #{@definition} is required\" }"
57
+ end
58
+
59
+ def definition_line
60
+ return unless @type || @default
61
+
62
+ "#{@item} = __dry_initializer_config__.definitions[:'#{@source}']"
63
+ end
64
+
65
+ def default_line
66
+ return unless @default
67
+
68
+ "#{@val} = instance_exec(&#{@item}.default) if #{@null} == #{@val}"
69
+ end
70
+
71
+ def coercion_line
72
+ return unless @type
73
+
74
+ arity = @type.is_a?(Proc) ? @type.arity : @type.method(:call).arity
75
+ type_call_params = \
76
+ arity.equal?(1) || arity.negative? ? @val : "#{@val}, self"
77
+
78
+ <<-COERCE
79
+ begin
80
+ unless #{@null} == #{@val}
81
+ #{@val} = #{@item}.type.call(#{type_call_params})
82
+ end
83
+ rescue Dry::Types::ConstraintError => e
84
+ raise Dry::Initializer::CoercionError.new(e, '#{@source}')
85
+ end
86
+ COERCE
87
+ end
88
+
89
+ def assignment_line
90
+ "#{@ivar} = #{@val}" \
91
+ " unless #{@null} == #{@val} && instance_variable_defined?(:#{@ivar})"
92
+ end
78
93
  end
79
94
  end
80
-
81
- def assignment_line
82
- "#{@ivar} = #{@val}" \
83
- " unless #{@null} == #{@val} && instance_variable_defined?(:#{@ivar})"
84
- end
85
95
  end
86
96
  end
@@ -1,57 +1,59 @@
1
- module Dry::Initializer::Builders
2
- # @private
3
- class Initializer
4
- require_relative 'signature'
5
- require_relative 'attribute'
6
-
7
- def self.[](config)
8
- new(config).call
9
- end
10
-
11
- def call
12
- lines.flatten.compact.join("\n")
13
- end
14
-
15
- private
16
-
17
- def initialize(config)
18
- @config = config
19
- @definitions = config.definitions.values
20
- end
21
-
22
- def lines
23
- [
24
- undef_line,
25
- define_line,
26
- params_lines,
27
- options_lines,
28
- end_line
29
- ]
30
- end
31
-
32
- def undef_line
33
- 'undef :__dry_initializer_initialize__' \
34
- ' if private_method_defined? :__dry_initializer_initialize__'
35
- end
36
-
37
- def define_line
38
- "private def __dry_initializer_initialize__(#{Signature[@config]})"
39
- end
40
-
41
- def params_lines
42
- @definitions.reject(&:option)
43
- .flat_map { |item| Attribute[item] }
44
- .map { |line| ' ' << line }
45
- end
46
-
47
- def options_lines
48
- @definitions.select(&:option)
49
- .flat_map { |item| Attribute[item] }
50
- .map { |line| ' ' << line }
51
- end
52
-
53
- def end_line
54
- 'end'
1
+ # frozen_string_literal: true
2
+
3
+ module Dry
4
+ module Initializer
5
+ module Builders
6
+ # @private
7
+ class Initializer
8
+ require_relative "signature"
9
+ require_relative "attribute"
10
+
11
+ def self.[](config)
12
+ new(config).call
13
+ end
14
+
15
+ def call
16
+ lines.flatten.compact.join("\n")
17
+ end
18
+
19
+ private
20
+
21
+ def initialize(config)
22
+ @config = config
23
+ @definitions = config.definitions.values
24
+ end
25
+
26
+ def lines
27
+ [
28
+ undef_line,
29
+ define_line,
30
+ params_lines,
31
+ options_lines,
32
+ end_line
33
+ ]
34
+ end
35
+
36
+ def undef_line
37
+ "undef :__dry_initializer_initialize__" \
38
+ " if private_method_defined? :__dry_initializer_initialize__"
39
+ end
40
+
41
+ def define_line
42
+ "private def __dry_initializer_initialize__(#{Signature[@config]})"
43
+ end
44
+
45
+ def params_lines
46
+ @definitions.reject(&:option).flat_map { Attribute[_1] }.map { " #{_1}" }
47
+ end
48
+
49
+ def options_lines
50
+ @definitions.select(&:option).flat_map { Attribute[_1] }.map { " #{_1}" }
51
+ end
52
+
53
+ def end_line
54
+ "end"
55
+ end
56
+ end
55
57
  end
56
58
  end
57
59
  end
@@ -1,52 +1,58 @@
1
- module Dry::Initializer::Builders
2
- # @private
3
- class Reader
4
- def self.[](definition)
5
- new(definition).call
6
- end
7
-
8
- def call
9
- lines.flatten.compact.join("\n")
10
- end
11
-
12
- private
13
-
14
- def initialize(definition)
15
- @target = definition.target
16
- @ivar = definition.ivar
17
- @null = definition.null
18
- @reader = definition.reader
19
- end
20
-
21
- def lines
22
- [undef_line, attribute_line, method_lines, type_line]
23
- end
24
-
25
- def undef_line
26
- "undef :#{@target} if method_defined?(:#{@target})" \
27
- " || private_method_defined?(:#{@target})" \
28
- " || protected_method_defined?(:#{@target})"
29
- end
30
-
31
- def attribute_line
32
- return unless @reader
33
-
34
- "attr_reader :#{@target}" unless @null
35
- end
36
-
37
- def method_lines
38
- return unless @reader
39
- return unless @null
40
-
41
- [
42
- "def #{@target}",
43
- " #{@ivar} unless Dry::Initializer::UNDEFINED == #{@ivar}",
44
- 'end'
45
- ]
46
- end
47
-
48
- def type_line
49
- "#{@reader} :#{@target}" if %i[private protected].include? @reader
1
+ # frozen_string_literal: true
2
+
3
+ module Dry
4
+ module Initializer
5
+ module Builders
6
+ # @private
7
+ class Reader
8
+ def self.[](definition)
9
+ new(definition).call
10
+ end
11
+
12
+ def call
13
+ lines.flatten.compact.join("\n")
14
+ end
15
+
16
+ private
17
+
18
+ def initialize(definition)
19
+ @target = definition.target
20
+ @ivar = definition.ivar
21
+ @null = definition.null
22
+ @reader = definition.reader
23
+ end
24
+
25
+ def lines
26
+ [undef_line, attribute_line, method_lines, type_line]
27
+ end
28
+
29
+ def undef_line
30
+ "undef :#{@target} if method_defined?(:#{@target})" \
31
+ " || private_method_defined?(:#{@target})" \
32
+ " || protected_method_defined?(:#{@target})"
33
+ end
34
+
35
+ def attribute_line
36
+ return unless @reader
37
+
38
+ "attr_reader :#{@target}" unless @null
39
+ end
40
+
41
+ def method_lines
42
+ return unless @reader
43
+ return unless @null
44
+
45
+ [
46
+ "def #{@target}",
47
+ " #{@ivar} unless Dry::Initializer::UNDEFINED == #{@ivar}",
48
+ "end"
49
+ ]
50
+ end
51
+
52
+ def type_line
53
+ "#{@reader} :#{@target}" if %i[private protected].include? @reader
54
+ end
55
+ end
50
56
  end
51
57
  end
52
58
  end
@@ -1,32 +1,38 @@
1
- module Dry::Initializer::Builders
2
- # @private
3
- class Signature
4
- def self.[](config)
5
- new(config).call
6
- end
1
+ # frozen_string_literal: true
7
2
 
8
- def call
9
- [*required_params, *optional_params, '*', options].compact.join(', ')
10
- end
3
+ module Dry
4
+ module Initializer
5
+ module Builders
6
+ # @private
7
+ class Signature
8
+ def self.[](config)
9
+ new(config).call
10
+ end
11
11
 
12
- private
12
+ def call
13
+ [*required_params, *optional_params, "*", options].compact.join(", ")
14
+ end
13
15
 
14
- def initialize(config)
15
- @config = config
16
- @options = config.options.any?
17
- @null = config.null ? 'Dry::Initializer::UNDEFINED' : 'nil'
18
- end
16
+ private
19
17
 
20
- def required_params
21
- @config.params.reject(&:optional).map(&:source)
22
- end
18
+ def initialize(config)
19
+ @config = config
20
+ @options = config.options.any?
21
+ @null = config.null ? "Dry::Initializer::UNDEFINED" : "nil"
22
+ end
23
23
 
24
- def optional_params
25
- @config.params.select(&:optional).map { |rec| "#{rec.source} = #{@null}" }
26
- end
24
+ def required_params
25
+ @config.params.reject(&:optional).map(&:source)
26
+ end
27
+
28
+ def optional_params
29
+ @config.params.select(&:optional).map { |rec| "#{rec.source} = #{@null}" }
30
+ end
27
31
 
28
- def options
29
- '**__dry_initializer_options__' if @options
32
+ def options
33
+ "**__dry_initializer_options__" if @options
34
+ end
35
+ end
30
36
  end
31
37
  end
32
38
  end
@@ -1,7 +1,11 @@
1
- module Dry::Initializer
2
- # @private
3
- module Builders
4
- require_relative 'builders/reader'
5
- require_relative 'builders/initializer'
1
+ # frozen_string_literal: true
2
+
3
+ module Dry
4
+ module Initializer
5
+ # @private
6
+ module Builders
7
+ require_relative "builders/reader"
8
+ require_relative "builders/initializer"
9
+ end
6
10
  end
7
11
  end