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