codependent 0.2 → 0.3
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/Changelog.md +20 -0
- data/Gemfile +2 -8
- data/Gemfile.lock +6 -0
- data/README.md +2 -29
- data/codependent.gemspec +9 -2
- data/lib/codependent/container.rb +1 -1
- data/lib/codependent/errors.rb +53 -0
- data/lib/codependent/injectable_builder.rb +13 -3
- data/lib/codependent/resolvers/root_resolver.rb +3 -3
- data/lib/codependent/validators/constructor_injection_validator.rb +5 -7
- data/lib/codependent/validators/provider_validator.rb +3 -3
- data/lib/codependent/validators/setter_injection_validator.rb +4 -3
- data/lib/codependent/validators/value_validator.rb +5 -7
- data/lib/codependent.rb +1 -0
- metadata +88 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 824b117cef6d2000cb55df3ed8793c75f2119d42
|
4
|
+
data.tar.gz: d83e83d6c90f343853e26a8f6d154798bc2e32ef
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 16364a8df976b2b7a6da996898d16c4210248d25bb3774d0a446001d10d2fdf73395027979d87c6e359efd086b713a33b40dece6127330b356519e2249956da6
|
7
|
+
data.tar.gz: 2c27d0c05a78fcf297225a43cfa2cefe69cec7ed20e644841750dfee3acb253b33ce58a1efda727e8ec5ee7fe3f645bc997c2caa11dcb09b4188155e2c198d1f
|
data/Changelog.md
CHANGED
@@ -3,3 +3,23 @@
|
|
3
3
|
### Features
|
4
4
|
|
5
5
|
* Initial Release
|
6
|
+
|
7
|
+
## 0.2 - New injection types!
|
8
|
+
|
9
|
+
### Features
|
10
|
+
|
11
|
+
* Constructor injection
|
12
|
+
* Value injection
|
13
|
+
* Provider functions
|
14
|
+
* Dependency type checking
|
15
|
+
* New DSL syntax
|
16
|
+
|
17
|
+
## 0.3 - Better error handling
|
18
|
+
|
19
|
+
### Features
|
20
|
+
|
21
|
+
* Validation errors are more descriptive and contain the ID of the injectable.
|
22
|
+
|
23
|
+
### Bug Fixes
|
24
|
+
|
25
|
+
* Dependencies that appear in multiple places in the dependency graph are injected properly.
|
data/Gemfile
CHANGED
@@ -1,10 +1,4 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
gem 'pry'
|
6
|
-
gem 'pry-byebug'
|
7
|
-
gem 'rubocop', '~> 0.40.0', require: false
|
8
|
-
gem 'rake'
|
9
|
-
gem 'simplecov', require: false
|
10
|
-
end
|
3
|
+
# Specify your gem's dependencies in pastafari.gemspec
|
4
|
+
gemspec
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -114,7 +114,7 @@ Codependent::Manager.container :my_container do
|
|
114
114
|
# This block is passed to a new container instance and uses the same syntax
|
115
115
|
# we've already seen.
|
116
116
|
instance :logger do
|
117
|
-
|
117
|
+
from_value Logger.new
|
118
118
|
end
|
119
119
|
end
|
120
120
|
|
@@ -131,33 +131,6 @@ Codependent::Manager.reset_container!(:my_container)
|
|
131
131
|
Codependent::Manager.reset!
|
132
132
|
```
|
133
133
|
|
134
|
-
### Class Definition Syntax
|
135
|
-
|
136
|
-
```ruby
|
137
|
-
# Not everyone wants to configure the container up front. You can define your
|
138
|
-
# dependencies in your class definitions with the Codependent Helper.
|
139
|
-
class UserRepository
|
140
|
-
extend Codependent::Helper
|
141
|
-
|
142
|
-
# Tell Codependent what to call this injectable and how it should be resolved:
|
143
|
-
singleton :user_repository do
|
144
|
-
# The syntax here is the same as before.
|
145
|
-
with_constructor { self.new }
|
146
|
-
depends_on :logger
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
class Logger
|
151
|
-
extend Codependent::Helper
|
152
|
-
|
153
|
-
# You can also specify the managed container into which this type should be
|
154
|
-
# defined:
|
155
|
-
instance :logger, in_container: :my_container do
|
156
|
-
with_constructor { self.new }
|
157
|
-
end
|
158
|
-
end
|
159
|
-
```
|
160
|
-
|
161
134
|
## Developing Codependent
|
162
135
|
|
163
136
|
### Building from source
|
@@ -166,5 +139,5 @@ end
|
|
166
139
|
2. Install dependencies: `bundle install`
|
167
140
|
3. Run the tests: `bundle exec rake ci`
|
168
141
|
4. Build a local copy of the gem: `gem build codependent.gemspec`
|
169
|
-
5. Install the gem locally: `gem install ./
|
142
|
+
5. Install the gem locally: `gem install ./codependent-0.2.gem`
|
170
143
|
6. Don't forget to version-bump the gemspec before publishing!
|
data/codependent.gemspec
CHANGED
@@ -1,11 +1,18 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'codependent'
|
3
|
-
s.version = '0.
|
4
|
-
s.date = '2017-02-
|
3
|
+
s.version = '0.3'
|
4
|
+
s.date = '2017-02-24'
|
5
5
|
s.summary = "A simple dependency injection library for Ruby."
|
6
6
|
s.authors = ["Joshua Tompkins"]
|
7
7
|
s.email = 'josh@joshtompkins.com'
|
8
8
|
s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
9
9
|
s.homepage = 'https://github.com/jtompkins/codependent'
|
10
10
|
s.license = 'MIT'
|
11
|
+
|
12
|
+
s.add_development_dependency 'rspec'
|
13
|
+
s.add_development_dependency 'pry'
|
14
|
+
s.add_development_dependency 'pry-byebug'
|
15
|
+
s.add_development_dependency 'rake'
|
16
|
+
s.add_development_dependency 'rubocop', '~> 0.40.0'
|
17
|
+
s.add_development_dependency 'simplecov'
|
11
18
|
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Codependent
|
2
|
+
module Errors
|
3
|
+
class CodependentError < StandardError; end
|
4
|
+
|
5
|
+
class MissingTypeError < CodependentError
|
6
|
+
def message
|
7
|
+
'Type injection requires a type.'
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class MissingKeywordArgError < CodependentError
|
12
|
+
def message
|
13
|
+
'All dependencies must appear as keyword arguments.'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class MissingAccessorError < CodependentError
|
18
|
+
def message
|
19
|
+
'All dependencies must have accessors.'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class NoConstructorArgsError < CodependentError
|
24
|
+
def message
|
25
|
+
'No constructor arguments.'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class MissingProviderBlockError < CodependentError
|
30
|
+
def message
|
31
|
+
'Providers must have a block.'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class ValueDependencyError < CodependentError
|
36
|
+
def message
|
37
|
+
'Value injectables may not have dependencies.'
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class NoValueError < CodependentError
|
42
|
+
def message
|
43
|
+
'Value injectables must have a value.'
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class ValueOnInstanceError < CodependentError
|
48
|
+
def message
|
49
|
+
'Value injectables cannot be singletons.'
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'codependent/injectable'
|
2
|
+
require 'codependent/errors'
|
2
3
|
|
3
4
|
require 'codependent/validators/value_validator'
|
4
5
|
require 'codependent/validators/provider_validator'
|
@@ -12,14 +13,15 @@ require 'codependent/resolvers/value_resolver'
|
|
12
13
|
|
13
14
|
module Codependent
|
14
15
|
class InjectableBuilder
|
15
|
-
def initialize(type)
|
16
|
+
def initialize(id, type)
|
17
|
+
@id = id
|
16
18
|
@type = type
|
17
19
|
@dependencies = []
|
18
20
|
@state = {}
|
19
21
|
@skip_checks = false
|
20
22
|
end
|
21
23
|
|
22
|
-
attr_reader :type, :dependencies, :state, :validator, :resolver
|
24
|
+
attr_reader :id, :type, :dependencies, :state, :validator, :resolver
|
23
25
|
|
24
26
|
def from_value(value)
|
25
27
|
@state = { value: value }
|
@@ -59,9 +61,17 @@ module Codependent
|
|
59
61
|
def build
|
60
62
|
return unless @validator
|
61
63
|
|
62
|
-
|
64
|
+
validate unless @skip_checks
|
63
65
|
|
64
66
|
Injectable.new(@type, @dependencies, @state, @resolver)
|
65
67
|
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def validate
|
72
|
+
@validator.new.(@type, @state, @dependencies)
|
73
|
+
rescue Codependent::Errors::CodependentError => e
|
74
|
+
raise "#{e.message} Check the configuration for #{id}."
|
75
|
+
end
|
66
76
|
end
|
67
77
|
end
|
@@ -26,7 +26,8 @@ module Codependent
|
|
26
26
|
|
27
27
|
def resolve_eager_dependencies(injectable_ids)
|
28
28
|
injectable_ids.reduce({}) do |acc, id|
|
29
|
-
acc
|
29
|
+
next acc if acc.key?(id)
|
30
|
+
acc.tap { |hash| hash[id] = resolve_value(id, acc) }
|
30
31
|
end
|
31
32
|
end
|
32
33
|
|
@@ -71,9 +72,8 @@ module Codependent
|
|
71
72
|
current = injectables[stack.pop]
|
72
73
|
|
73
74
|
current.dependencies.each do |dep_id|
|
74
|
-
|
75
|
+
stack.push(dep_id) unless dependencies.include?(dep_id)
|
75
76
|
dependencies.unshift(dep_id)
|
76
|
-
stack.push(dep_id)
|
77
77
|
end
|
78
78
|
end
|
79
79
|
|
@@ -1,12 +1,10 @@
|
|
1
|
+
require 'codependent/errors'
|
2
|
+
|
1
3
|
module Codependent
|
2
4
|
module Validators
|
3
5
|
class ConstructorInjectionValidator
|
4
|
-
MISSING_TYPE_ERROR = 'Constructor injection requires a type to be specified.'.freeze
|
5
|
-
MISSING_DEPENDENCY_KEYWORDS_ERROR = 'All dependencies must appear as keyword arguments to the constructor.'.freeze
|
6
|
-
NO_ARGS_WITH_DEPENDENCIES_ERROR = 'Constructor injection requires the constructor to receive arguments.'.freeze
|
7
|
-
|
8
6
|
def call(_, state, dependencies)
|
9
|
-
raise
|
7
|
+
raise Codependent::Errors::MissingTypeError unless state[:type]
|
10
8
|
|
11
9
|
return unless dependencies.count > 0
|
12
10
|
|
@@ -30,7 +28,7 @@ module Codependent
|
|
30
28
|
def validate_constructor_params(klass, dependencies)
|
31
29
|
params = klass.instance_method(:initialize).parameters
|
32
30
|
|
33
|
-
raise
|
31
|
+
raise Codependent::Errors::NoConstructorArgsError if params.count == 0
|
34
32
|
|
35
33
|
return unless all_keywords?(params)
|
36
34
|
|
@@ -38,7 +36,7 @@ module Codependent
|
|
38
36
|
|
39
37
|
return if params_for_all_dependencies?(dependencies, parameter_names)
|
40
38
|
|
41
|
-
raise
|
39
|
+
raise Codependent::Errors::MissingKeywordArgError
|
42
40
|
end
|
43
41
|
end
|
44
42
|
end
|
@@ -1,10 +1,10 @@
|
|
1
|
+
require 'codependent/errors'
|
2
|
+
|
1
3
|
module Codependent
|
2
4
|
module Validators
|
3
5
|
class ProviderValidator
|
4
|
-
NO_BLOCK_ERROR = 'Provider injectables must have a block.'.freeze
|
5
|
-
|
6
6
|
def call(_, state, _)
|
7
|
-
raise
|
7
|
+
raise Codependent::Errors::MissingProviderBlockError unless state[:provider]
|
8
8
|
end
|
9
9
|
end
|
10
10
|
end
|
@@ -1,11 +1,12 @@
|
|
1
|
+
require 'codependent/errors'
|
2
|
+
|
1
3
|
module Codependent
|
2
4
|
module Validators
|
3
5
|
class SetterInjectionValidator
|
4
|
-
MISSING_TYPE_ERROR = 'Setter injection requires a type to be specified.'.freeze
|
5
6
|
MISSING_ACCESSOR_KEYWORDS_ERROR = 'All dependencies must appear as accessors on the class.'.freeze
|
6
7
|
|
7
8
|
def call(_, state, dependencies)
|
8
|
-
raise
|
9
|
+
raise Codependent::Errors::MissingTypeError unless state[:type]
|
9
10
|
|
10
11
|
return unless dependencies.count > 0
|
11
12
|
|
@@ -17,7 +18,7 @@ module Codependent
|
|
17
18
|
def validate_setters(klass, dependencies)
|
18
19
|
dependencies.each do |dep_id|
|
19
20
|
unless klass.method_defined? "#{dep_id}=".to_sym
|
20
|
-
raise
|
21
|
+
raise Codependent::Errors::MissingAccessorError
|
21
22
|
end
|
22
23
|
end
|
23
24
|
end
|
@@ -1,17 +1,15 @@
|
|
1
|
+
require 'codependent/errors'
|
2
|
+
|
1
3
|
module Codependent
|
2
4
|
module Validators
|
3
5
|
class ValueValidator
|
4
|
-
SINGLETON_ERROR = 'Value injectables are only allowed on singletons.'.freeze
|
5
|
-
NIL_VALUE_ERROR = 'Value injectables must not be nil.'.freeze
|
6
|
-
NO_DEPENDENCIES_ERROR = 'Value injectables may not have dependencies'.freeze
|
7
|
-
|
8
6
|
def call(type, state, dependencies)
|
9
|
-
raise
|
10
|
-
raise
|
7
|
+
raise Codependent::Errors::ValueOnInstanceError unless type == :singleton
|
8
|
+
raise Codependent::Errors::NoValueError unless state[:value]
|
11
9
|
|
12
10
|
no_dependencies = !dependencies || dependencies.count != 0
|
13
11
|
|
14
|
-
raise
|
12
|
+
raise Codependent::Errors::ValueDependencyError if no_dependencies
|
15
13
|
end
|
16
14
|
end
|
17
15
|
end
|
data/lib/codependent.rb
CHANGED
@@ -2,6 +2,7 @@ require 'codependent/manager'
|
|
2
2
|
require 'codependent/container'
|
3
3
|
require 'codependent/injectable'
|
4
4
|
require 'codependent/injectable_builder'
|
5
|
+
require 'codependent/errors'
|
5
6
|
|
6
7
|
require 'codependent/resolvers/root_resolver'
|
7
8
|
require 'codependent/resolvers/eager_type_resolver'
|
metadata
CHANGED
@@ -1,15 +1,99 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: codependent
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.3'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joshua Tompkins
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-02-
|
12
|
-
dependencies:
|
11
|
+
date: 2017-02-24 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rspec
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: pry
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: pry-byebug
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rubocop
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 0.40.0
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 0.40.0
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: simplecov
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
13
97
|
description:
|
14
98
|
email: josh@joshtompkins.com
|
15
99
|
executables: []
|
@@ -29,6 +113,7 @@ files:
|
|
29
113
|
- codependent.gemspec
|
30
114
|
- lib/codependent.rb
|
31
115
|
- lib/codependent/container.rb
|
116
|
+
- lib/codependent/errors.rb
|
32
117
|
- lib/codependent/injectable.rb
|
33
118
|
- lib/codependent/injectable_builder.rb
|
34
119
|
- lib/codependent/manager.rb
|