dry-initializer 3.0.4 → 3.1.0

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