dumpling 0.2.0 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 07ff2f1a56d0fabcfefe29dec5322d7ff2f57eb6
4
- data.tar.gz: bead658711229742bb88e919d913af3257a19883
3
+ metadata.gz: 0f35ab64a03b696579240966d5b7bc3319c004e3
4
+ data.tar.gz: b6ed032e93f0ad3c83b404034ff4d4e0e4dd7ce3
5
5
  SHA512:
6
- metadata.gz: cf8af125eed37639db305a1fe6639cdb0c91fb2402d24826423909b05f3d53d7bc2531442244917a5597b53d0652ea77e3485cf3c5281b8247757be9385c3d82
7
- data.tar.gz: 3b2946aeb843ff9f916b25e495a1d577a6ce5cf91a966464f64a630dc28bb9d56a11ac68bcd9d1302068efe11c96c09020dfecc5a28aaf14bf6bcd344df53b7e
6
+ metadata.gz: 16d1109b05bd418eb468d03e9f143f9ac3be88ee93c8bc522dff96308b26f48a335326a67249e12d0aea471b8f5457546a183d1554eb71e70bc1fc9ea42d1f0d
7
+ data.tar.gz: c255e615a20097481c66d7baf3b0627e338f878c6c2a9c3c16ed89d534e7e4ef31d3160c77f95c5edfcee971cf67c4b43b9f56efd77090131a3bbbaedc39bdcd
@@ -0,0 +1,14 @@
1
+ module Dumpling
2
+ class ClassValidator
3
+ def validate(specification)
4
+ unless specification.class.nil? || specification.instance.nil?
5
+ fail Errors::Service::Invalid,
6
+ 'Do not define both #class and #instance at the same time'
7
+ end
8
+
9
+ if specification.class.nil? && specification.instance.nil?
10
+ fail Errors::Service::Invalid, 'Define #class or #instance'
11
+ end
12
+ end
13
+ end
14
+ end
@@ -1,53 +1,67 @@
1
1
  module Dumpling
2
2
  class Container
3
- attr_writer :validator_class
4
-
5
3
  def initialize
6
- @registry = Registry.new
7
- @validator_class = SpecificationValidator
4
+ @services = Registry.new
5
+ @abstract_services = Registry.new
6
+ end
7
+
8
+ def configure(&block)
9
+ instance_eval(&block)
10
+ self
8
11
  end
9
12
 
10
13
  def set(id, &block)
11
- fail(Errors::Container::Duplicate, id) if @registry.has?(id)
14
+ fail(Errors::Container::Duplicate, id) if @services.has?(id)
12
15
 
13
16
  specification = create_specification(&block)
14
- @registry.set(id, specification)
17
+ @services.set(id, specification)
18
+ id
19
+ end
15
20
 
21
+ def abstract(id, &block)
22
+ fail(Errors::Container::Duplicate, id) if @abstract_services.has?(id)
23
+
24
+ specification = create_abstract_specification(&block)
25
+ @abstract_services.set(id, specification)
16
26
  id
17
27
  end
18
28
 
19
29
  def get(id)
20
- fail(Errors::Container::Missing, id) unless @registry.has?(id)
21
- specification = @registry.get(id)
22
- instance = build_instance(specification)
23
- inject_dependencies(instance, specification)
24
- instance
30
+ fail(Errors::Container::Missing, id) unless @services.has?(id)
31
+
32
+ specification = @services.get(id)
33
+ build_service(specification)
25
34
  end
26
35
 
27
36
  alias :[] get
28
37
 
29
- def configure(&block)
30
- instance_eval(&block)
31
- self
32
- end
33
-
34
38
  private
35
39
 
36
40
  def create_specification
37
- specification = Specification.new
38
- yield specification
39
- @validator_class.new(@registry.keys, specification).validate!
40
- specification
41
+ spec = ServiceSpecification.new
42
+ yield spec
43
+ class_validator.validate(spec)
44
+ dependencies_validator.validate(spec)
45
+ spec
46
+ end
47
+
48
+ def create_abstract_specification
49
+ spec = ServiceSpecification.new
50
+ yield spec
51
+ dependencies_validator.validate(spec)
52
+ spec
53
+ end
54
+
55
+ def class_validator
56
+ @class_validator ||= ClassValidator.new
41
57
  end
42
58
 
43
- def build_instance(specification)
44
- specification.class.nil? ? specification.instance : specification.class.new
59
+ def dependencies_validator
60
+ @dependencies_validator ||= DependenciesValidator.new(@services.keys, @abstract_services.keys)
45
61
  end
46
62
 
47
- def inject_dependencies(instance, specification)
48
- specification.dependencies.each do |dependency|
49
- instance.send("#{dependency[:attribute]}=", get(dependency[:id]))
50
- end
63
+ def build_service(specification)
64
+ ServiceBuilder.new(@services, @abstract_services).build(specification)
51
65
  end
52
66
  end
53
67
  end
@@ -0,0 +1,31 @@
1
+ module Dumpling
2
+ class DependenciesValidator
3
+ def initialize(service_ids, abstract_service_ids)
4
+ @service_ids = service_ids
5
+ @abstract_service_ids = abstract_service_ids
6
+ end
7
+
8
+ def validate(specification)
9
+ missing_services = missing_dependencies(specification).map(&:inspect)
10
+ missing_abstract_services = missing_abstract_dependencies(specification).map do |id|
11
+ "#{id.inspect}(abstract)"
12
+ end
13
+ missing_services.concat(missing_abstract_services)
14
+
15
+ unless missing_services.empty?
16
+ fail Errors::Service::MissingDependencies, missing_services.join(', ')
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def missing_dependencies(specification)
23
+ dependency_ids = specification.dependencies.keys
24
+ dependency_ids.reject { |id| @service_ids.include?(id) }
25
+ end
26
+
27
+ def missing_abstract_dependencies(specification)
28
+ specification.abstract_services.reject { |id| @abstract_service_ids.include?(id) }
29
+ end
30
+ end
31
+ end
@@ -1,6 +1,6 @@
1
1
  module Dumpling
2
2
  module Errors
3
- module Specification
3
+ module Service
4
4
  class Invalid < BaseError
5
5
  end
6
6
 
@@ -0,0 +1,37 @@
1
+ module Dumpling
2
+ class ServiceBuilder
3
+ def initialize(services, abstract_services)
4
+ @services = services
5
+ @abstract_services = abstract_services
6
+ end
7
+
8
+ def build(specification)
9
+ instance = service_instance(specification)
10
+ dependencies = service_dependencies(specification)
11
+ dependencies.each do |service_id, options|
12
+ service_specification = @services.get(service_id)
13
+ instance.send("#{options[:attribute]}=", build(service_specification))
14
+ end
15
+ instance
16
+ end
17
+
18
+ private
19
+
20
+ def service_instance(specification)
21
+ specification.class.nil? ? specification.instance : specification.class.new
22
+ end
23
+
24
+ def service_dependencies(specification)
25
+ dependencies = {}
26
+
27
+ specification.abstract_services.each do |abstract_service_id|
28
+ abstract_service_specification = @abstract_services.get(abstract_service_id)
29
+ abstract_service_dependencies = service_dependencies(abstract_service_specification)
30
+ dependencies.merge!(abstract_service_dependencies)
31
+ end
32
+
33
+ dependencies.merge!(specification.dependencies)
34
+ dependencies
35
+ end
36
+ end
37
+ end
@@ -1,9 +1,10 @@
1
1
  module Dumpling
2
- class Specification < BasicObject
3
- attr_accessor :dependencies
2
+ class ServiceSpecification < BasicObject
3
+ attr_reader :dependencies, :abstract_services
4
4
 
5
5
  def initialize
6
- self.dependencies = []
6
+ @dependencies = {}
7
+ @abstract_services = []
7
8
  end
8
9
 
9
10
  def class(klass = nil)
@@ -15,7 +16,13 @@ module Dumpling
15
16
  end
16
17
 
17
18
  def dependency(id, attribute: nil)
18
- dependencies << { id: id, attribute: (attribute || guess_attribute(id)).to_sym }
19
+ dependencies[id] = { attribute: (attribute || guess_attribute(id)).to_sym }
20
+ end
21
+
22
+ def include(*ids)
23
+ abstract_services.concat ids
24
+
25
+ nil
19
26
  end
20
27
 
21
28
  private
@@ -1,7 +1,7 @@
1
1
  module Dumpling
2
2
  module Version
3
3
  MAJOR = 0
4
- MINOR = 2
4
+ MINOR = 3
5
5
  TINY = 0
6
6
  PRE = nil
7
7
 
data/lib/dumpling.rb CHANGED
@@ -4,9 +4,11 @@ module Dumpling
4
4
  require 'dumpling/version'
5
5
  require 'dumpling/errors/base_error'
6
6
  require 'dumpling/errors/container'
7
- require 'dumpling/errors/specification'
8
- require 'dumpling/specification'
9
- require 'dumpling/specification_validator'
7
+ require 'dumpling/errors/service'
8
+ require 'dumpling/service_specification'
9
+ require 'dumpling/service_builder'
10
+ require 'dumpling/class_validator'
11
+ require 'dumpling/dependencies_validator'
10
12
  require 'dumpling/registry'
11
13
  require 'dumpling/container'
12
14
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dumpling
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anton Kuzmenko
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-02-08 00:00:00.000000000 Z
11
+ date: 2016-03-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -99,13 +99,15 @@ files:
99
99
  - bin/setup
100
100
  - dumpling.gemspec
101
101
  - lib/dumpling.rb
102
+ - lib/dumpling/class_validator.rb
102
103
  - lib/dumpling/container.rb
104
+ - lib/dumpling/dependencies_validator.rb
103
105
  - lib/dumpling/errors/base_error.rb
104
106
  - lib/dumpling/errors/container.rb
105
- - lib/dumpling/errors/specification.rb
107
+ - lib/dumpling/errors/service.rb
106
108
  - lib/dumpling/registry.rb
107
- - lib/dumpling/specification.rb
108
- - lib/dumpling/specification_validator.rb
109
+ - lib/dumpling/service_builder.rb
110
+ - lib/dumpling/service_specification.rb
109
111
  - lib/dumpling/version.rb
110
112
  homepage: https://github.com/antonkuzmenko/dumpling
111
113
  licenses:
@@ -1,41 +0,0 @@
1
- module Dumpling
2
- class SpecificationValidator
3
- def initialize(id_list, specification)
4
- @id_list = id_list
5
- @specification = specification
6
- end
7
-
8
- def validate!
9
- validate_value
10
- validate_dependencies
11
- end
12
-
13
- private
14
-
15
- def validate_value
16
- unless @specification.class.nil? || @specification.instance.nil?
17
- fail Errors::Specification::Invalid,
18
- 'Do not define both #class and #instance at the same time'
19
- end
20
-
21
- if @specification.class.nil? && @specification.instance.nil?
22
- fail Errors::Specification::Invalid, 'Define #class or #instance'
23
- end
24
- end
25
-
26
- def validate_dependencies
27
- missing_deps = missing_dependencies
28
-
29
- unless missing_deps.empty?
30
- fail Errors::Specification::MissingDependencies, missing_deps.join(', ')
31
- end
32
- end
33
-
34
- def missing_dependencies
35
- @specification
36
- .dependencies
37
- .map { |e| e[:id] }
38
- .reject { |e| @id_list.include?(e) }
39
- end
40
- end
41
- end