dry-initializer 0.11.0 → 2.5.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.
- checksums.yaml +4 -4
- data/.codeclimate.yml +8 -0
- data/.gitignore +1 -0
- data/.rspec +1 -0
- data/.rubocop.yml +14 -62
- data/.travis.yml +15 -11
- data/CHANGELOG.md +538 -158
- data/Gemfile +2 -2
- data/LICENSE.txt +1 -1
- data/README.md +6 -6
- data/Rakefile +2 -41
- data/benchmarks/{several_defaults.rb → compare_several_defaults.rb} +4 -4
- data/benchmarks/{without_options.rb → plain_options.rb} +21 -10
- data/benchmarks/{params.rb → plain_params.rb} +20 -9
- data/benchmarks/{with_types.rb → with_coercion.rb} +23 -16
- data/benchmarks/with_defaults.rb +19 -8
- data/benchmarks/{with_types_and_defaults.rb → with_defaults_and_coercion.rb} +21 -12
- data/dry-initializer.gemspec +4 -4
- data/lib/dry/initializer/builders/attribute.rb +81 -0
- data/lib/dry/initializer/builders/initializer.rb +61 -0
- data/lib/dry/initializer/builders/reader.rb +50 -0
- data/lib/dry/initializer/builders/signature.rb +32 -0
- data/lib/dry/initializer/builders.rb +7 -0
- data/lib/dry/initializer/config.rb +172 -0
- data/lib/dry/initializer/definition.rb +116 -0
- data/lib/dry/initializer/dispatchers.rb +44 -0
- data/lib/dry/initializer/dsl.rb +43 -0
- data/lib/dry/initializer/mixin/local.rb +19 -0
- data/lib/dry/initializer/mixin/root.rb +10 -0
- data/lib/dry/initializer/mixin.rb +8 -70
- data/lib/dry/initializer.rb +49 -12
- data/lib/tasks/benchmark.rake +41 -0
- data/lib/tasks/profile.rake +78 -0
- data/spec/attributes_spec.rb +38 -0
- data/spec/coercion_of_nil_spec.rb +25 -0
- data/spec/custom_dispatchers_spec.rb +35 -0
- data/spec/custom_initializer_spec.rb +1 -1
- data/spec/default_values_spec.rb +8 -8
- data/spec/definition_spec.rb +107 -0
- data/spec/invalid_default_spec.rb +2 -2
- data/spec/missed_default_spec.rb +3 -3
- data/spec/optional_spec.rb +35 -8
- data/spec/options_tolerance_spec.rb +1 -1
- data/spec/public_attributes_utility_spec.rb +22 -0
- data/spec/reader_spec.rb +11 -11
- data/spec/repetitive_definitions_spec.rb +41 -21
- data/spec/several_assignments_spec.rb +41 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/subclassing_spec.rb +7 -3
- data/spec/type_argument_spec.rb +1 -1
- data/spec/type_constraint_spec.rb +38 -7
- data/spec/value_coercion_via_dry_types_spec.rb +12 -4
- metadata +37 -40
- data/benchmarks/options.rb +0 -54
- data/benchmarks/params_vs_options.rb +0 -35
- data/lib/dry/initializer/builder.rb +0 -100
- data/lib/dry/initializer/errors/default_value_error.rb +0 -6
- data/lib/dry/initializer/errors/order_error.rb +0 -7
- data/lib/dry/initializer/errors/plugin_error.rb +0 -6
- data/lib/dry/initializer/errors/redefinition_error.rb +0 -5
- data/lib/dry/initializer/errors/type_constraint_error.rb +0 -5
- data/lib/dry/initializer/errors.rb +0 -10
- data/lib/dry/initializer/plugins/base.rb +0 -47
- data/lib/dry/initializer/plugins/default_proc.rb +0 -28
- data/lib/dry/initializer/plugins/signature.rb +0 -28
- data/lib/dry/initializer/plugins/type_constraint.rb +0 -21
- data/lib/dry/initializer/plugins/variable_setter.rb +0 -30
- data/lib/dry/initializer/plugins.rb +0 -10
- data/lib/dry/initializer/signature.rb +0 -61
- data/spec/base_spec.rb +0 -21
- data/spec/container_spec.rb +0 -45
- data/spec/default_nil_spec.rb +0 -17
- data/spec/plugin_registry_spec.rb +0 -45
- 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
|
49
|
+
extend Dry::Initializer
|
50
50
|
|
51
51
|
# Params of the initializer along with corresponding readers
|
52
|
-
param :name,
|
53
|
-
param :role, default:
|
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:
|
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.
|
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.
|
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
|
-
|
8
|
-
|
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
|
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
|
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
|
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
|
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
|
-
|
4
|
-
|
3
|
+
require "dry-initializer"
|
4
|
+
class DryTest
|
5
|
+
extend Dry::Initializer[undefined: false]
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
@bar = bar
|
9
|
-
end
|
7
|
+
option :foo
|
8
|
+
option :bar
|
10
9
|
end
|
11
10
|
|
12
|
-
|
13
|
-
|
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
|
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
|
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
|
-
|
4
|
-
|
3
|
+
require "dry-initializer"
|
4
|
+
class DryTest
|
5
|
+
extend Dry::Initializer[undefined: false]
|
5
6
|
|
6
|
-
|
7
|
-
|
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
|
-
|
15
|
-
|
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,
|
21
|
-
option :bar,
|
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
|
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
|
data/benchmarks/with_defaults.rb
CHANGED
@@ -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
|
-
|
10
|
-
|
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
|
data/dry-initializer.gemspec
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
Gem::Specification.new do |gem|
|
2
2
|
gem.name = "dry-initializer"
|
3
|
-
gem.version = "
|
3
|
+
gem.version = "2.5.0"
|
4
4
|
gem.author = ["Vladimir Kochnev (marshall-lee)", "Andrew Kozin (nepalez)"]
|
5
|
-
gem.email =
|
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.
|
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.
|
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
|