dry-initializer 0.11.0 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +8 -0
  3. data/.gitignore +1 -0
  4. data/.rspec +1 -0
  5. data/.rubocop.yml +14 -62
  6. data/.travis.yml +15 -11
  7. data/CHANGELOG.md +538 -158
  8. data/Gemfile +2 -2
  9. data/LICENSE.txt +1 -1
  10. data/README.md +6 -6
  11. data/Rakefile +2 -41
  12. data/benchmarks/{several_defaults.rb → compare_several_defaults.rb} +4 -4
  13. data/benchmarks/{without_options.rb → plain_options.rb} +21 -10
  14. data/benchmarks/{params.rb → plain_params.rb} +20 -9
  15. data/benchmarks/{with_types.rb → with_coercion.rb} +23 -16
  16. data/benchmarks/with_defaults.rb +19 -8
  17. data/benchmarks/{with_types_and_defaults.rb → with_defaults_and_coercion.rb} +21 -12
  18. data/dry-initializer.gemspec +4 -4
  19. data/lib/dry/initializer/builders/attribute.rb +81 -0
  20. data/lib/dry/initializer/builders/initializer.rb +61 -0
  21. data/lib/dry/initializer/builders/reader.rb +50 -0
  22. data/lib/dry/initializer/builders/signature.rb +32 -0
  23. data/lib/dry/initializer/builders.rb +7 -0
  24. data/lib/dry/initializer/config.rb +172 -0
  25. data/lib/dry/initializer/definition.rb +116 -0
  26. data/lib/dry/initializer/dispatchers.rb +44 -0
  27. data/lib/dry/initializer/dsl.rb +43 -0
  28. data/lib/dry/initializer/mixin/local.rb +19 -0
  29. data/lib/dry/initializer/mixin/root.rb +10 -0
  30. data/lib/dry/initializer/mixin.rb +8 -70
  31. data/lib/dry/initializer.rb +49 -12
  32. data/lib/tasks/benchmark.rake +41 -0
  33. data/lib/tasks/profile.rake +78 -0
  34. data/spec/attributes_spec.rb +38 -0
  35. data/spec/coercion_of_nil_spec.rb +25 -0
  36. data/spec/custom_dispatchers_spec.rb +35 -0
  37. data/spec/custom_initializer_spec.rb +1 -1
  38. data/spec/default_values_spec.rb +8 -8
  39. data/spec/definition_spec.rb +107 -0
  40. data/spec/invalid_default_spec.rb +2 -2
  41. data/spec/missed_default_spec.rb +3 -3
  42. data/spec/optional_spec.rb +35 -8
  43. data/spec/options_tolerance_spec.rb +1 -1
  44. data/spec/public_attributes_utility_spec.rb +22 -0
  45. data/spec/reader_spec.rb +11 -11
  46. data/spec/repetitive_definitions_spec.rb +41 -21
  47. data/spec/several_assignments_spec.rb +41 -0
  48. data/spec/spec_helper.rb +7 -0
  49. data/spec/subclassing_spec.rb +7 -3
  50. data/spec/type_argument_spec.rb +1 -1
  51. data/spec/type_constraint_spec.rb +38 -7
  52. data/spec/value_coercion_via_dry_types_spec.rb +12 -4
  53. metadata +37 -40
  54. data/benchmarks/options.rb +0 -54
  55. data/benchmarks/params_vs_options.rb +0 -35
  56. data/lib/dry/initializer/builder.rb +0 -100
  57. data/lib/dry/initializer/errors/default_value_error.rb +0 -6
  58. data/lib/dry/initializer/errors/order_error.rb +0 -7
  59. data/lib/dry/initializer/errors/plugin_error.rb +0 -6
  60. data/lib/dry/initializer/errors/redefinition_error.rb +0 -5
  61. data/lib/dry/initializer/errors/type_constraint_error.rb +0 -5
  62. data/lib/dry/initializer/errors.rb +0 -10
  63. data/lib/dry/initializer/plugins/base.rb +0 -47
  64. data/lib/dry/initializer/plugins/default_proc.rb +0 -28
  65. data/lib/dry/initializer/plugins/signature.rb +0 -28
  66. data/lib/dry/initializer/plugins/type_constraint.rb +0 -21
  67. data/lib/dry/initializer/plugins/variable_setter.rb +0 -30
  68. data/lib/dry/initializer/plugins.rb +0 -10
  69. data/lib/dry/initializer/signature.rb +0 -61
  70. data/spec/base_spec.rb +0 -21
  71. data/spec/container_spec.rb +0 -45
  72. data/spec/default_nil_spec.rb +0 -17
  73. data/spec/plugin_registry_spec.rb +0 -45
  74. data/spec/renaming_options_spec.rb +0 -20
data/Gemfile CHANGED
@@ -4,8 +4,6 @@ source "https://rubygems.org"
4
4
  gemspec
5
5
 
6
6
  group :benchmarks do
7
- gem "benchmark-ips", "~> 2.5"
8
-
9
7
  if RUBY_VERSION < "2.4"
10
8
  gem "activesupport", "< 5"
11
9
  else
@@ -15,9 +13,11 @@ group :benchmarks do
15
13
  gem "active_attr"
16
14
  gem "anima"
17
15
  gem "attr_extras"
16
+ gem "benchmark-ips", "~> 2.5"
18
17
  gem "concord"
19
18
  gem "fast_attributes"
20
19
  gem "kwattr"
20
+ gem "ruby-prof"
21
21
  gem "value_struct"
22
22
  gem "values"
23
23
  gem "virtus"
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2016 Andrew Kozin (nepalez), Vladimir Kochnev (marshall-lee)
3
+ Copyright (c) 2016-2017 Andrew Kozin (nepalez), Vladimir Kochnev (marshall-lee)
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -46,13 +46,13 @@ require 'dry-initializer'
46
46
  require 'dry-types'
47
47
 
48
48
  class User
49
- extend Dry::Initializer::Mixin
49
+ extend Dry::Initializer
50
50
 
51
51
  # Params of the initializer along with corresponding readers
52
- param :name, type: Dry::Types["strict.string"]
53
- param :role, default: proc { 'customer' }
52
+ param :name, proc(&:to_s)
53
+ param :role, default: -> { 'customer' }
54
54
  # Options of the initializer along with corresponding readers
55
- option :admin, default: proc { false }
55
+ option :admin, default: -> { false }
56
56
  option :vip, optional: true
57
57
  end
58
58
 
@@ -70,11 +70,11 @@ See full documentation on the [Dry project official site][docs]
70
70
 
71
71
  ## Benchmarks
72
72
 
73
- The `dry-initializer` is pretty fast for rubies 2.2+ [comparing to other libraries][benchmarks].
73
+ The `dry-initializer` is pretty fast for rubies 2.3+ [comparing to other libraries][benchmarks].
74
74
 
75
75
  ## Compatibility
76
76
 
77
- Tested under rubies [compatible to MRI 2.2+](.travis.yml).
77
+ Tested under rubies [compatible to MRI 2.3+](.travis.yml).
78
78
 
79
79
  ## Contributing
80
80
 
data/Rakefile CHANGED
@@ -4,44 +4,5 @@ Bundler::GemHelper.install_tasks
4
4
  require "rspec/core/rake_task"
5
5
  RSpec::Core::RakeTask.new :default
6
6
 
7
- namespace :benchmark do
8
- desc "Runs benchmarks without options"
9
- task :without_options do
10
- system "ruby benchmarks/without_options.rb"
11
- end
12
-
13
- desc "Runs benchmarks for several defaults"
14
- task :several_defaults do
15
- system "ruby benchmarks/several_defaults.rb"
16
- end
17
-
18
- desc "Runs benchmarks for defaults of params vs. options"
19
- task :params_vs_options do
20
- system "ruby benchmarks/params_vs_options.rb"
21
- end
22
-
23
- desc "Runs benchmarks with types"
24
- task :with_types do
25
- system "ruby benchmarks/with_types.rb"
26
- end
27
-
28
- desc "Runs benchmarks with defaults"
29
- task :with_defaults do
30
- system "ruby benchmarks/with_defaults.rb"
31
- end
32
-
33
- desc "Runs benchmarks with types and defaults"
34
- task :with_types_and_defaults do
35
- system "ruby benchmarks/with_types_and_defaults.rb"
36
- end
37
-
38
- desc "Runs benchmarks for plain params"
39
- task :params do
40
- system "ruby benchmarks/params.rb"
41
- end
42
-
43
- desc "Runs benchmarks various opts"
44
- task :options do
45
- system "ruby benchmarks/options.rb"
46
- end
47
- end
7
+ load "lib/tasks/benchmark.rake"
8
+ load "lib/tasks/profile.rake"
@@ -2,7 +2,7 @@ Bundler.require(:benchmarks)
2
2
 
3
3
  require "dry-initializer"
4
4
  class WithoutDefaults
5
- extend Dry::Initializer::Mixin
5
+ extend Dry::Initializer
6
6
 
7
7
  param :foo
8
8
  param :bar
@@ -10,7 +10,7 @@ class WithoutDefaults
10
10
  end
11
11
 
12
12
  class WithOneDefault
13
- extend Dry::Initializer::Mixin
13
+ extend Dry::Initializer
14
14
 
15
15
  param :foo
16
16
  param :bar
@@ -18,7 +18,7 @@ class WithOneDefault
18
18
  end
19
19
 
20
20
  class WithTwoDefaults
21
- extend Dry::Initializer::Mixin
21
+ extend Dry::Initializer
22
22
 
23
23
  param :foo
24
24
  param :bar, default: proc { "BAR" }
@@ -26,7 +26,7 @@ class WithTwoDefaults
26
26
  end
27
27
 
28
28
  class WithThreeDefaults
29
- extend Dry::Initializer::Mixin
29
+ extend Dry::Initializer
30
30
 
31
31
  param :foo, default: proc { "FOO" }
32
32
  param :bar, default: proc { "BAR" }
@@ -1,22 +1,29 @@
1
1
  Bundler.require(:benchmarks)
2
2
 
3
- class PlainRubyTest
4
- attr_reader :foo, :bar
3
+ require "dry-initializer"
4
+ class DryTest
5
+ extend Dry::Initializer[undefined: false]
5
6
 
6
- def initialize(foo:, bar:)
7
- @foo = foo
8
- @bar = bar
9
- end
7
+ option :foo
8
+ option :bar
10
9
  end
11
10
 
12
- require "dry-initializer"
13
- class DryTest
14
- extend Dry::Initializer::Mixin
11
+ class DryTestUndefined
12
+ extend Dry::Initializer
15
13
 
16
14
  option :foo
17
15
  option :bar
18
16
  end
19
17
 
18
+ class PlainRubyTest
19
+ attr_reader :foo, :bar
20
+
21
+ def initialize(options = {})
22
+ @foo = options[:foo]
23
+ @bar = options[:bar]
24
+ end
25
+ end
26
+
20
27
  require "anima"
21
28
  class AnimaTest
22
29
  include Anima.new(:foo, :bar)
@@ -27,7 +34,7 @@ class KwattrTest
27
34
  kwattr :foo, :bar
28
35
  end
29
36
 
30
- puts "Benchmark for instantiation without options"
37
+ puts "Benchmark for instantiation with plain options"
31
38
 
32
39
  Benchmark.ips do |x|
33
40
  x.config time: 15, warmup: 10
@@ -40,6 +47,10 @@ Benchmark.ips do |x|
40
47
  DryTest.new foo: "FOO", bar: "BAR"
41
48
  end
42
49
 
50
+ x.report("dry-initializer (with UNDEFINED)") do
51
+ DryTestUndefined.new foo: "FOO", bar: "BAR"
52
+ end
53
+
43
54
  x.report("anima") do
44
55
  AnimaTest.new foo: "FOO", bar: "BAR"
45
56
  end
@@ -1,5 +1,20 @@
1
1
  Bundler.require(:benchmarks)
2
2
 
3
+ require "dry-initializer"
4
+ class DryTest
5
+ extend Dry::Initializer[undefined: false]
6
+
7
+ param :foo
8
+ param :bar
9
+ end
10
+
11
+ class DryTestUndefined
12
+ extend Dry::Initializer
13
+
14
+ param :foo
15
+ param :bar
16
+ end
17
+
3
18
  class PlainRubyTest
4
19
  attr_reader :foo, :bar
5
20
 
@@ -11,14 +26,6 @@ end
11
26
 
12
27
  StructTest = Struct.new(:foo, :bar)
13
28
 
14
- require "dry-initializer"
15
- class DryTest
16
- extend Dry::Initializer::Mixin
17
-
18
- param :foo
19
- param :bar
20
- end
21
-
22
29
  require "concord"
23
30
  class ConcordTest
24
31
  include Concord.new(:foo, :bar)
@@ -36,7 +43,7 @@ class AttrExtrasText
36
43
  attr_reader :foo, :bar
37
44
  end
38
45
 
39
- puts "Benchmark for instantiation of plain params"
46
+ puts "Benchmark for instantiation with plain params"
40
47
 
41
48
  Benchmark.ips do |x|
42
49
  x.config time: 15, warmup: 10
@@ -61,6 +68,10 @@ Benchmark.ips do |x|
61
68
  DryTest.new "FOO", "BAR"
62
69
  end
63
70
 
71
+ x.report("dry-initializer (with UNDEFINED)") do
72
+ DryTestUndefined.new "FOO", "BAR"
73
+ end
74
+
64
75
  x.report("concord") do
65
76
  ConcordTest.new "FOO", "BAR"
66
77
  end
@@ -1,24 +1,27 @@
1
1
  Bundler.require(:benchmarks)
2
2
 
3
- class PlainRubyTest
4
- attr_reader :foo, :bar
3
+ require "dry-initializer"
4
+ class DryTest
5
+ extend Dry::Initializer[undefined: false]
5
6
 
6
- def initialize(foo:, bar:)
7
- @foo = foo
8
- @bar = bar
9
- fail TypeError unless String === @foo
10
- fail TypeError unless String === @bar
11
- end
7
+ option :foo, proc(&:to_s)
8
+ option :bar, proc(&:to_s)
12
9
  end
13
10
 
14
- require "dry-initializer"
15
- require "dry/initializer/types"
16
- class DryTest
17
- extend Dry::Initializer::Mixin
18
- extend Dry::Initializer::Types
11
+ class DryTestUndefined
12
+ extend Dry::Initializer
19
13
 
20
- option :foo, type: String
21
- option :bar, type: String
14
+ option :foo, proc(&:to_s)
15
+ option :bar, proc(&:to_s)
16
+ end
17
+
18
+ class PlainRubyTest
19
+ attr_reader :foo, :bar
20
+
21
+ def initialize(options)
22
+ @foo = options[:foo].to_s
23
+ @bar = options[:bar].to_s
24
+ end
22
25
  end
23
26
 
24
27
  require "virtus"
@@ -39,7 +42,7 @@ class FastAttributesTest
39
42
  end
40
43
  end
41
44
 
42
- puts "Benchmark for instantiation with type constraints"
45
+ puts "Benchmark for instantiation with coercion"
43
46
 
44
47
  Benchmark.ips do |x|
45
48
  x.config time: 15, warmup: 10
@@ -52,6 +55,10 @@ Benchmark.ips do |x|
52
55
  DryTest.new foo: "FOO", bar: "BAR"
53
56
  end
54
57
 
58
+ x.report("dry-initializer (with UNDEFINED)") do
59
+ DryTestUndefined.new foo: "FOO", bar: "BAR"
60
+ end
61
+
55
62
  x.report("virtus") do
56
63
  VirtusTest.new foo: "FOO", bar: "BAR"
57
64
  end
@@ -1,5 +1,20 @@
1
1
  Bundler.require(:benchmarks)
2
2
 
3
+ require "dry-initializer"
4
+ class DryTest
5
+ extend Dry::Initializer[undefined: false]
6
+
7
+ option :foo, default: -> { "FOO" }
8
+ option :bar, default: -> { "BAR" }
9
+ end
10
+
11
+ class DryTestUndefined
12
+ extend Dry::Initializer
13
+
14
+ option :foo, default: -> { "FOO" }
15
+ option :bar, default: -> { "BAR" }
16
+ end
17
+
3
18
  class PlainRubyTest
4
19
  attr_reader :foo, :bar
5
20
 
@@ -9,14 +24,6 @@ class PlainRubyTest
9
24
  end
10
25
  end
11
26
 
12
- require "dry-initializer"
13
- class DryTest
14
- extend Dry::Initializer::Mixin
15
-
16
- option :foo, default: proc { "FOO" }
17
- option :bar, default: proc { "BAR" }
18
- end
19
-
20
27
  require "kwattr"
21
28
  class KwattrTest
22
29
  kwattr foo: "FOO", bar: "BAR"
@@ -43,6 +50,10 @@ Benchmark.ips do |x|
43
50
  DryTest.new
44
51
  end
45
52
 
53
+ x.report("dry-initializer (with UNDEFINED)") do
54
+ DryTestUndefined.new
55
+ end
56
+
46
57
  x.report("kwattr") do
47
58
  KwattrTest.new
48
59
  end
@@ -1,26 +1,31 @@
1
1
  Bundler.require(:benchmarks)
2
2
 
3
+ require "dry-initializer"
4
+ class DryTest
5
+ extend Dry::Initializer[undefined: false]
6
+
7
+ option :foo, proc(&:to_s), default: -> { "FOO" }
8
+ option :bar, proc(&:to_s), default: -> { "BAR" }
9
+ end
10
+
11
+ class DryTestUndefined
12
+ extend Dry::Initializer
13
+
14
+ option :foo, proc(&:to_s), default: -> { "FOO" }
15
+ option :bar, proc(&:to_s), default: -> { "BAR" }
16
+ end
17
+
3
18
  class PlainRubyTest
4
19
  attr_reader :foo, :bar
5
20
 
6
21
  def initialize(foo: "FOO", bar: "BAR")
7
22
  @foo = foo
8
23
  @bar = bar
9
- fail TypeError unless String === @foo
10
- fail TypeError unless String === @bar
24
+ raise TypeError unless String === @foo
25
+ raise TypeError unless String === @bar
11
26
  end
12
27
  end
13
28
 
14
- require "dry-initializer"
15
- require "dry/initializer/types"
16
- class DryTest
17
- extend Dry::Initializer::Mixin
18
- extend Dry::Initializer::Types
19
-
20
- option :foo, type: String, default: proc { "FOO" }
21
- option :bar, type: String, default: proc { "BAR" }
22
- end
23
-
24
29
  require "virtus"
25
30
  class VirtusTest
26
31
  include Virtus.model
@@ -42,6 +47,10 @@ Benchmark.ips do |x|
42
47
  DryTest.new
43
48
  end
44
49
 
50
+ x.report("dry-initializer (with UNDEFINED)") do
51
+ DryTest.new
52
+ end
53
+
45
54
  x.report("virtus") do
46
55
  VirtusTest.new
47
56
  end
@@ -1,8 +1,8 @@
1
1
  Gem::Specification.new do |gem|
2
2
  gem.name = "dry-initializer"
3
- gem.version = "0.11.0"
3
+ gem.version = "2.5.0"
4
4
  gem.author = ["Vladimir Kochnev (marshall-lee)", "Andrew Kozin (nepalez)"]
5
- gem.email = ["hashtable@yandex.ru", "andrew.kozin@gmail.com"]
5
+ gem.email = "andrew.kozin@gmail.com"
6
6
  gem.homepage = "https://github.com/dryrb/dry-initializer"
7
7
  gem.summary = "DSL for declaring params and options of the initializer"
8
8
  gem.license = "MIT"
@@ -11,10 +11,10 @@ Gem::Specification.new do |gem|
11
11
  gem.test_files = gem.files.grep(/^spec/)
12
12
  gem.extra_rdoc_files = Dir["README.md", "LICENSE", "CHANGELOG.md"]
13
13
 
14
- gem.required_ruby_version = ">= 2.2"
14
+ gem.required_ruby_version = ">= 2.3"
15
15
 
16
16
  gem.add_development_dependency "rspec", "~> 3.0"
17
17
  gem.add_development_dependency "rake", "> 10"
18
18
  gem.add_development_dependency "dry-types", "> 0.5.1"
19
- gem.add_development_dependency "rubocop", "~> 0.42"
19
+ gem.add_development_dependency "rubocop", "~> 0.49.0"
20
20
  end
@@ -0,0 +1,81 @@
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
+ @optional ? optional_reader : required_reader
45
+ end
46
+
47
+ def optional_reader
48
+ "#{@val} = #{@opts}.fetch(:'#{@source}', #{@null})"
49
+ end
50
+
51
+ def required_reader
52
+ "#{@val} = #{@opts}.fetch(:'#{@source}')" \
53
+ " { raise KeyError, \"\#{self.class}: #{@definition} is required\" }"
54
+ end
55
+
56
+ def definition_line
57
+ return unless @type || @default
58
+ "#{@item} = __dry_initializer_config__.definitions[:'#{@source}']"
59
+ end
60
+
61
+ def default_line
62
+ return unless @default
63
+ "#{@val} = instance_exec(&#{@item}.default) if #{@null} == #{@val}"
64
+ end
65
+
66
+ def coercion_line
67
+ return unless @type
68
+ arity = @type.is_a?(Proc) ? @type.arity : @type.method(:call).arity
69
+ if arity.abs == 1
70
+ "#{@val} = #{@item}.type.call(#{@val}) unless #{@null} == #{@val}"
71
+ else
72
+ "#{@val} = #{@item}.type.call(#{@val}, self) unless #{@null} == #{@val}"
73
+ end
74
+ end
75
+
76
+ def assignment_line
77
+ "#{@ivar} = #{@val}" \
78
+ " unless #{@null} == #{@val} && instance_variable_defined?(:#{@ivar})"
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,61 @@
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"
55
+ end
56
+
57
+ def private_line
58
+ "private :__dry_initializer_initialize__"
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,50 @@
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
+ "attr_reader :#{@target}" unless @null
34
+ end
35
+
36
+ def method_lines
37
+ return unless @reader
38
+ return unless @null
39
+ [
40
+ "def #{@target}",
41
+ " #{@ivar} unless Dry::Initializer::UNDEFINED == #{@ivar}",
42
+ "end"
43
+ ]
44
+ end
45
+
46
+ def type_line
47
+ "#{@reader} :#{@target}" if %i[private protected].include? @reader
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,32 @@
1
+ module Dry::Initializer::Builders
2
+ # @private
3
+ class Signature
4
+ def self.[](config)
5
+ new(config).call
6
+ end
7
+
8
+ def call
9
+ [*required_params, *optional_params, "*", options].compact.join(", ")
10
+ end
11
+
12
+ private
13
+
14
+ def initialize(config)
15
+ @config = config
16
+ @options = config.options.any?
17
+ @null = config.null ? "Dry::Initializer::UNDEFINED" : "nil"
18
+ end
19
+
20
+ def required_params
21
+ @config.params.reject(&:optional).map(&:source)
22
+ end
23
+
24
+ def optional_params
25
+ @config.params.select(&:optional).map { |rec| "#{rec.source} = #{@null}" }
26
+ end
27
+
28
+ def options
29
+ "**__dry_initializer_options__" if @options
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,7 @@
1
+ module Dry::Initializer
2
+ # @private
3
+ module Builders
4
+ require_relative "builders/reader"
5
+ require_relative "builders/initializer"
6
+ end
7
+ end