dry-auto_inject 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +4 -4
- data/CHANGELOG.md +16 -0
- data/dry-auto_inject.gemspec +2 -3
- data/lib/dry/auto_inject.rb +0 -8
- data/lib/dry/auto_inject/dependency_map.rb +2 -2
- data/lib/dry/auto_inject/method_parameters.rb +92 -0
- data/lib/dry/auto_inject/strategies/args.rb +11 -18
- data/lib/dry/auto_inject/strategies/hash.rb +4 -3
- data/lib/dry/auto_inject/strategies/kwargs.rb +54 -35
- data/lib/dry/auto_inject/version.rb +1 -1
- metadata +22 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4d3bcb1fb6fde005af77e71608739263f5866bf4cd1b00c4ad7c9cd6d6a6d61a
|
4
|
+
data.tar.gz: b8eb767e090882f4a6102c594b7e1da1798c550ea0fbfa734a693c032ee2ba3e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fe6dc512e6e3d0de8ca362cb5d34c069dd3f88b1fd90f77056281c073d659003a687195637ef6fbac24763362dc41cc536a24f7ff98cb5225c34856b855ee431
|
7
|
+
data.tar.gz: a3c1629d8437135fd16c5e02599ed6acf1d6bb55fd114f139855cc1c7ea6275bca9f726a59a9e63668698fe2a7c410d7a5a26485a054936ea5f175b62f7186f7
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,19 @@
|
|
1
|
+
# 0.6.0 / 2018-11-29
|
2
|
+
|
3
|
+
### Changed
|
4
|
+
|
5
|
+
- [BREAKING] 0.6.0 supports Ruby 2.3 and above. If you're on 2.3 keep in mind its EOL is scheduled at the end of March, 2019
|
6
|
+
|
7
|
+
### Added
|
8
|
+
|
9
|
+
- Enhanced support for integrating with existing constructors. The kwargs strategy will now pass dependencies up to the next constructor if it accepts an arbitrary number of arguments with `*args`. Note that this change may break existing code though we think it's unlikely to happen. If something doesn't work for you please report and we'll try to sort it out (flash-gordon + timriley in [#48](https://github.com/dry-rb/dry-auto_inject/pull/48))
|
10
|
+
|
11
|
+
### Fixed
|
12
|
+
|
13
|
+
- A couple of regressions were fixed along the way, see [#46](https://github.com/dry-rb/dry-auto_inject/issues/46) and [#49](https://github.com/dry-rb/dry-auto_inject/issues/49) (flash-gordon + timriley in [#48](https://github.com/dry-rb/dry-auto_inject/pull/48))
|
14
|
+
|
15
|
+
[Compare v0.5.0...v0.6.0](https://github.com/dry-rb/dry-auto_inject/compare/v0.5.0...v0.6.0)
|
16
|
+
|
1
17
|
# 0.5.0 / 2018-11-09
|
2
18
|
|
3
19
|
### Changed
|
data/dry-auto_inject.gemspec
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
# coding: utf-8
|
2
1
|
# frozen_string_literal: true
|
3
2
|
|
4
3
|
lib = File.expand_path('../lib', __FILE__)
|
@@ -20,11 +19,11 @@ Gem::Specification.new do |spec|
|
|
20
19
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
20
|
spec.require_paths = ['lib']
|
22
21
|
|
23
|
-
spec.required_ruby_version = '>= 2.
|
22
|
+
spec.required_ruby_version = '>= 2.3.0'
|
24
23
|
|
25
24
|
spec.add_runtime_dependency 'dry-container', '>= 0.3.4'
|
26
25
|
|
27
26
|
spec.add_development_dependency 'bundler'
|
28
27
|
spec.add_development_dependency 'rake'
|
29
|
-
spec.add_development_dependency 'rspec'
|
28
|
+
spec.add_development_dependency 'rspec', '~> 3.8'
|
30
29
|
end
|
data/lib/dry/auto_inject.rb
CHANGED
@@ -43,12 +43,4 @@ module Dry
|
|
43
43
|
def self.AutoInject(container, options = {})
|
44
44
|
AutoInject::Builder.new(container, options)
|
45
45
|
end
|
46
|
-
|
47
|
-
module AutoInject
|
48
|
-
# @api private
|
49
|
-
def self.super_method(klass, method)
|
50
|
-
method = klass.instance_method(method)
|
51
|
-
method unless method.owner.equal?(klass)
|
52
|
-
end
|
53
|
-
end
|
54
46
|
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module Dry
|
4
|
+
module AutoInject
|
5
|
+
# @api private
|
6
|
+
class MethodParameters
|
7
|
+
PASS_THROUGH = [[:rest]]
|
8
|
+
|
9
|
+
if RUBY_VERSION >= '2.4.4.' && !defined? JRUBY_VERSION
|
10
|
+
def self.of(obj, name)
|
11
|
+
Enumerator.new do |y|
|
12
|
+
begin
|
13
|
+
method = obj.instance_method(name)
|
14
|
+
rescue NameError
|
15
|
+
end
|
16
|
+
|
17
|
+
loop do
|
18
|
+
break if method.nil?
|
19
|
+
|
20
|
+
y << MethodParameters.new(method.parameters)
|
21
|
+
method = method.super_method
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
else
|
26
|
+
# see https://bugs.ruby-lang.org/issues/13973
|
27
|
+
def self.of(obj, name)
|
28
|
+
Enumerator.new do |y|
|
29
|
+
ancestors = obj.ancestors
|
30
|
+
|
31
|
+
loop do
|
32
|
+
klass = ancestors.shift
|
33
|
+
break if klass.nil?
|
34
|
+
|
35
|
+
begin
|
36
|
+
method = klass.instance_method(name)
|
37
|
+
|
38
|
+
next unless method.owner.equal?(klass)
|
39
|
+
rescue NameError
|
40
|
+
next
|
41
|
+
end
|
42
|
+
|
43
|
+
y << MethodParameters.new(method.parameters)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
attr_reader :parameters
|
50
|
+
|
51
|
+
def initialize(parameters)
|
52
|
+
@parameters = parameters
|
53
|
+
end
|
54
|
+
|
55
|
+
def splat?
|
56
|
+
return @splat if defined? @splat
|
57
|
+
@splat = parameters.any? { |type, _| type == :rest }
|
58
|
+
end
|
59
|
+
|
60
|
+
def sequential_arguments?
|
61
|
+
return @sequential_arguments if defined? @sequential_arguments
|
62
|
+
@sequential_arguments = parameters.any? { |type, _|
|
63
|
+
type == :req || type == :opt
|
64
|
+
}
|
65
|
+
end
|
66
|
+
|
67
|
+
def keyword_names
|
68
|
+
@keyword_names ||= parameters.each_with_object(Set.new) { |(type, name), names|
|
69
|
+
names << name if type == :key || type == :keyreq
|
70
|
+
}
|
71
|
+
end
|
72
|
+
|
73
|
+
def keyword?(name)
|
74
|
+
keyword_names.include?(name)
|
75
|
+
end
|
76
|
+
|
77
|
+
def empty?
|
78
|
+
parameters.empty?
|
79
|
+
end
|
80
|
+
|
81
|
+
def length
|
82
|
+
parameters.length
|
83
|
+
end
|
84
|
+
|
85
|
+
def pass_through?
|
86
|
+
parameters.eql?(PASS_THROUGH)
|
87
|
+
end
|
88
|
+
|
89
|
+
EMPTY = new([])
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'dry/auto_inject/strategies/constructor'
|
4
|
+
require 'dry/auto_inject/method_parameters'
|
4
5
|
|
5
6
|
module Dry
|
6
7
|
module AutoInject
|
@@ -22,12 +23,15 @@ module Dry
|
|
22
23
|
end
|
23
24
|
|
24
25
|
def define_initialize(klass)
|
25
|
-
|
26
|
+
super_parameters = MethodParameters.of(klass, :initialize).each do |ps|
|
27
|
+
# Look upwards past `def foo(*)` methods until we get an explicit list of parameters
|
28
|
+
break ps unless ps.pass_through?
|
29
|
+
end
|
26
30
|
|
27
|
-
if
|
31
|
+
if super_parameters.empty?
|
28
32
|
define_initialize_with_params
|
29
33
|
else
|
30
|
-
define_initialize_with_splat(
|
34
|
+
define_initialize_with_splat(super_parameters)
|
31
35
|
end
|
32
36
|
end
|
33
37
|
|
@@ -42,31 +46,20 @@ module Dry
|
|
42
46
|
RUBY
|
43
47
|
end
|
44
48
|
|
45
|
-
def define_initialize_with_splat(
|
46
|
-
|
49
|
+
def define_initialize_with_splat(super_parameters)
|
50
|
+
super_pass = if super_parameters.splat?
|
47
51
|
'*args'
|
48
52
|
else
|
49
|
-
"*args
|
53
|
+
"*args.take(#{super_parameters.length})"
|
50
54
|
end
|
51
55
|
|
52
56
|
instance_mod.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
53
57
|
def initialize(*args)
|
54
58
|
#{dependency_map.names.map.with_index { |name, i| "@#{name} = args[#{i}]" }.join("\n")}
|
55
|
-
super(#{
|
59
|
+
super(#{super_pass})
|
56
60
|
end
|
57
61
|
RUBY
|
58
62
|
end
|
59
|
-
|
60
|
-
def find_super(klass, method_name)
|
61
|
-
super_method = Dry::AutoInject.super_method(klass, method_name)
|
62
|
-
|
63
|
-
# Look upwards past `def foo(*)` methods until we get an explicit list of parameters
|
64
|
-
while super_method && super_method.parameters == [[:rest]]
|
65
|
-
super_method = Dry::AutoInject.super_method(super_method.owner, :initialize)
|
66
|
-
end
|
67
|
-
|
68
|
-
super_method
|
69
|
-
end
|
70
63
|
end
|
71
64
|
|
72
65
|
register :args, Args
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'dry/auto_inject/strategies/constructor'
|
4
|
+
require 'dry/auto_inject/method_parameters'
|
4
5
|
|
5
6
|
module Dry
|
6
7
|
module AutoInject
|
@@ -22,13 +23,13 @@ module Dry
|
|
22
23
|
end
|
23
24
|
|
24
25
|
def define_initialize(klass)
|
25
|
-
|
26
|
-
|
26
|
+
super_params = MethodParameters.of(klass, :initialize).first
|
27
|
+
super_pass = super_params.empty? ? '' : 'options'
|
27
28
|
|
28
29
|
instance_mod.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
29
30
|
def initialize(options)
|
30
31
|
#{dependency_map.names.map { |name| "@#{name} = options[:#{name}] unless !options.key?(#{name}) && instance_variable_defined?(:'@#{name}')" }.join("\n")}
|
31
|
-
super(#{
|
32
|
+
super(#{super_pass})
|
32
33
|
end
|
33
34
|
RUBY
|
34
35
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'dry/auto_inject/strategies/constructor'
|
4
|
+
require 'dry/auto_inject/method_parameters'
|
4
5
|
|
5
6
|
module Dry
|
6
7
|
module AutoInject
|
@@ -11,7 +12,7 @@ module Dry
|
|
11
12
|
|
12
13
|
def define_new
|
13
14
|
class_mod.class_exec(container, dependency_map) do |container, dependency_map|
|
14
|
-
map = dependency_map.to_h
|
15
|
+
map = dependency_map.to_h
|
15
16
|
|
16
17
|
define_method :new do |*args, **kwargs|
|
17
18
|
map.each do |name, identifier|
|
@@ -24,59 +25,77 @@ module Dry
|
|
24
25
|
end
|
25
26
|
|
26
27
|
def define_initialize(klass)
|
27
|
-
|
28
|
+
super_parameters = MethodParameters.of(klass, :initialize).each do |ps|
|
29
|
+
# Look upwards past `def foo(*)` methods until we get an explicit list of parameters
|
30
|
+
break ps unless ps.pass_through?
|
31
|
+
end
|
28
32
|
|
29
|
-
if
|
30
|
-
|
33
|
+
if super_parameters.splat? || super_parameters.sequential_arguments?
|
34
|
+
define_initialize_with_splat(super_parameters)
|
31
35
|
else
|
32
|
-
|
36
|
+
define_initialize_with_keywords(super_parameters)
|
33
37
|
end
|
34
38
|
|
35
39
|
self
|
36
40
|
end
|
37
41
|
|
38
|
-
def define_initialize_with_keywords
|
39
|
-
|
42
|
+
def define_initialize_with_keywords(super_parameters)
|
43
|
+
assign_dependencies = method(:assign_dependencies)
|
44
|
+
slice_kwargs = method(:slice_kwargs)
|
40
45
|
|
41
|
-
instance_mod.
|
42
|
-
|
43
|
-
|
44
|
-
super()
|
45
|
-
end
|
46
|
-
RUBY
|
46
|
+
instance_mod.class_exec do
|
47
|
+
define_method :initialize do |**kwargs|
|
48
|
+
assign_dependencies.(kwargs, self)
|
47
49
|
|
48
|
-
|
50
|
+
super_kwargs = slice_kwargs.(kwargs, super_parameters)
|
51
|
+
|
52
|
+
if super_kwargs.any?
|
53
|
+
super(super_kwargs)
|
54
|
+
else
|
55
|
+
super()
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
49
59
|
end
|
50
60
|
|
51
|
-
def define_initialize_with_splat(
|
52
|
-
|
53
|
-
|
54
|
-
}
|
61
|
+
def define_initialize_with_splat(super_parameters)
|
62
|
+
assign_dependencies = method(:assign_dependencies)
|
63
|
+
slice_kwargs = method(:slice_kwargs)
|
55
64
|
|
56
|
-
instance_mod.class_exec
|
65
|
+
instance_mod.class_exec do
|
57
66
|
define_method :initialize do |*args, **kwargs|
|
58
|
-
|
59
|
-
# Assign instance variables, but only if the ivar is not
|
60
|
-
# previously defined (this improves compatibility with objects
|
61
|
-
# initialized in unconventional ways)
|
62
|
-
instance_variable_set :"@#{name}", kwargs[name] unless kwargs[name].nil? && instance_variable_defined?(:"@#{name}")
|
63
|
-
end
|
64
|
-
|
65
|
-
super_kwargs = kwargs.each_with_object({}) { |(key, _), hsh|
|
66
|
-
if !dependency_map.names.include?(key) || super_kwarg_names.include?(key)
|
67
|
-
hsh[key] = kwargs[key]
|
68
|
-
end
|
69
|
-
}
|
67
|
+
assign_dependencies.(kwargs, self)
|
70
68
|
|
71
|
-
if
|
72
|
-
super(*args,
|
69
|
+
if super_parameters.splat?
|
70
|
+
super(*args, kwargs)
|
73
71
|
else
|
74
|
-
|
72
|
+
super_kwargs = slice_kwargs.(kwargs, super_parameters)
|
73
|
+
|
74
|
+
if super_kwargs.any?
|
75
|
+
super(*args, super_kwargs)
|
76
|
+
else
|
77
|
+
super(*args)
|
78
|
+
end
|
75
79
|
end
|
76
80
|
end
|
77
81
|
end
|
82
|
+
end
|
78
83
|
|
79
|
-
|
84
|
+
def assign_dependencies(kwargs, destination)
|
85
|
+
dependency_map.names.each do |name|
|
86
|
+
# Assign instance variables, but only if the ivar is not
|
87
|
+
# previously defined (this improves compatibility with objects
|
88
|
+
# initialized in unconventional ways)
|
89
|
+
if kwargs.key?(name) || !destination.instance_variable_defined?(:"@#{name}")
|
90
|
+
destination.instance_variable_set :"@#{name}", kwargs[name]
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def slice_kwargs(kwargs, super_parameters)
|
96
|
+
kwargs.select do |key|
|
97
|
+
!dependency_map.names.include?(key) || super_parameters.keyword?(key)
|
98
|
+
end
|
80
99
|
end
|
81
100
|
end
|
82
101
|
|
metadata
CHANGED
@@ -1,72 +1,72 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dry-auto_inject
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Piotr Solnica
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-11-
|
11
|
+
date: 2018-11-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name: dry-container
|
15
14
|
requirement: !ruby/object:Gem::Requirement
|
16
15
|
requirements:
|
17
16
|
- - ">="
|
18
17
|
- !ruby/object:Gem::Version
|
19
18
|
version: 0.3.4
|
20
|
-
|
19
|
+
name: dry-container
|
21
20
|
prerelease: false
|
21
|
+
type: :runtime
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 0.3.4
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name: bundler
|
29
28
|
requirement: !ruby/object:Gem::Requirement
|
30
29
|
requirements:
|
31
30
|
- - ">="
|
32
31
|
- !ruby/object:Gem::Version
|
33
32
|
version: '0'
|
34
|
-
|
33
|
+
name: bundler
|
35
34
|
prerelease: false
|
35
|
+
type: :development
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name: rake
|
43
42
|
requirement: !ruby/object:Gem::Requirement
|
44
43
|
requirements:
|
45
44
|
- - ">="
|
46
45
|
- !ruby/object:Gem::Version
|
47
46
|
version: '0'
|
48
|
-
|
47
|
+
name: rake
|
49
48
|
prerelease: false
|
49
|
+
type: :development
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name: rspec
|
57
56
|
requirement: !ruby/object:Gem::Requirement
|
58
57
|
requirements:
|
59
|
-
- - "
|
58
|
+
- - "~>"
|
60
59
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
62
|
-
|
60
|
+
version: '3.8'
|
61
|
+
name: rspec
|
63
62
|
prerelease: false
|
63
|
+
type: :development
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - "
|
66
|
+
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
69
|
-
description:
|
68
|
+
version: '3.8'
|
69
|
+
description:
|
70
70
|
email:
|
71
71
|
- piotr.solnica@gmail.com
|
72
72
|
executables: []
|
@@ -93,6 +93,7 @@ files:
|
|
93
93
|
- lib/dry/auto_inject/builder.rb
|
94
94
|
- lib/dry/auto_inject/dependency_map.rb
|
95
95
|
- lib/dry/auto_inject/injector.rb
|
96
|
+
- lib/dry/auto_inject/method_parameters.rb
|
96
97
|
- lib/dry/auto_inject/strategies.rb
|
97
98
|
- lib/dry/auto_inject/strategies/args.rb
|
98
99
|
- lib/dry/auto_inject/strategies/constructor.rb
|
@@ -104,7 +105,7 @@ homepage: https://github.com/dryrb/dry-auto_inject
|
|
104
105
|
licenses:
|
105
106
|
- MIT
|
106
107
|
metadata: {}
|
107
|
-
post_install_message:
|
108
|
+
post_install_message:
|
108
109
|
rdoc_options: []
|
109
110
|
require_paths:
|
110
111
|
- lib
|
@@ -112,16 +113,16 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
112
113
|
requirements:
|
113
114
|
- - ">="
|
114
115
|
- !ruby/object:Gem::Version
|
115
|
-
version: 2.
|
116
|
+
version: 2.3.0
|
116
117
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
117
118
|
requirements:
|
118
119
|
- - ">="
|
119
120
|
- !ruby/object:Gem::Version
|
120
121
|
version: '0'
|
121
122
|
requirements: []
|
122
|
-
rubyforge_project:
|
123
|
-
rubygems_version: 2.7.
|
124
|
-
signing_key:
|
123
|
+
rubyforge_project:
|
124
|
+
rubygems_version: 2.7.6
|
125
|
+
signing_key:
|
125
126
|
specification_version: 4
|
126
127
|
summary: Container-agnostic automatic constructor injection
|
127
128
|
test_files: []
|