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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9346a0d2621442d6fba3e69e244895fb5a4c22dc
4
- data.tar.gz: ff00bf9084921b52e50dbeba357ff06a8eadcaa7
3
+ metadata.gz: 824b117cef6d2000cb55df3ed8793c75f2119d42
4
+ data.tar.gz: d83e83d6c90f343853e26a8f6d154798bc2e32ef
5
5
  SHA512:
6
- metadata.gz: 4d9d0327496277dad897ce11b73abd6548ed3f97d107d17e1bc844958e35bb42191ecd5321c17a6c3c9ecd2ab04f5d4888de3224bcdb3026910f0f283fa33765
7
- data.tar.gz: 3a8a641f957db178008be0848fde2813c10c15430cd79d3fa970962d95b5426efeaf3dda1feca61031f5c9ebe7c1122def7d9cf4c756816ce6f0e3bdb9d3384d
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
- group :development do
4
- gem 'rspec'
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
@@ -1,3 +1,8 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ codependent (0.3)
5
+
1
6
  GEM
2
7
  remote: https://rubygems.org/
3
8
  specs:
@@ -52,6 +57,7 @@ PLATFORMS
52
57
  ruby
53
58
 
54
59
  DEPENDENCIES
60
+ codependent!
55
61
  pry
56
62
  pry-byebug
57
63
  rake
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
- with_constructor { Logger.new }
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 ./Codependent-0.1.gem`
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.2'
4
- s.date = '2017-02-23'
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
@@ -50,7 +50,7 @@ module Codependent
50
50
  end
51
51
 
52
52
  def add_injectable!(id, type, config_block)
53
- builder = Codependent::InjectableBuilder.new(type)
53
+ builder = Codependent::InjectableBuilder.new(id, type)
54
54
 
55
55
  builder.instance_eval(&config_block)
56
56
 
@@ -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
- @validator.new.(@type, @state, @dependencies) unless @skip_checks
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.merge(id => resolve_value(id, 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
- next if dependencies.include?(dep_id)
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 MISSING_TYPE_ERROR unless state[:type]
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 NO_ARGS_WITH_DEPENDENCIES_ERROR if params.count == 0
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 MISSING_DEPENDENCY_KEYWORDS_ERROR
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 NO_BLOCK_ERROR unless state[:provider]
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 MISSING_TYPE_ERROR unless state[:type]
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 MISSING_ACCESSOR_KEYWORDS_ERROR
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 SINGLETON_ERROR unless type == :singleton
10
- raise NIL_VALUE_ERROR unless state[:value]
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 NO_DEPENDENCIES_ERROR if no_dependencies
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.2'
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-23 00:00:00.000000000 Z
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