corindon 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a434327fdcd84d86831c646b72ff25fc3cd31b039372aae53ec049ce7ecc7f0b
4
- data.tar.gz: 84f16cdae405704f1332e10b15e4e406d735c051d01d1dfd23b0cbace986e68b
3
+ metadata.gz: 3d803035372216a30b75af02572aac4a1978e1f0d687c6425d26074913abfb1f
4
+ data.tar.gz: '007096e0f7cfa51fc6b85d1b4a4c63ef920b13a6f6f8bd638313b9c7ddd4743b'
5
5
  SHA512:
6
- metadata.gz: b819f64edf34893ec6af428914c3b41f70b1f7718a2c0acd88c6ce5d5b51664a6c5d866131c20161ebf4d34180d1e011a018ffc88b27038128982d094461e479
7
- data.tar.gz: 9b1c58294f04fd4612c889ff537c2343c2bded16a44c30b0e8af9b15443e28caef5683f0ec0734624786e03aa88a5a942c61b9ef36efa0888ec7515c89fbd772
6
+ metadata.gz: 5a9fdc84c38dd60b28bedc5469305c6cbaaf52a3291f140494b3aab2f010a717afa54e797681aeb140f99700fef50688ead340301acf55e8322701f0048edae1
7
+ data.tar.gz: b616cdbbefa1d2f84104082bb28deea30af5bdced64600a0d28ccd59f595928ed270de394f38a5c8040159973298213836315c74b2543d6828b292af0b1bc806
@@ -15,8 +15,10 @@ Gem::Specification.new do |s|
15
15
 
16
16
  s.required_ruby_version = '>= 2.6.0'
17
17
 
18
+ s.add_dependency 'semantic', '~> 1.6'
18
19
  s.add_dependency 'zeitwerk', '~> 2.3'
19
20
 
21
+ s.add_development_dependency 'bundler'
20
22
  s.add_development_dependency 'minitest', '~> 5.14'
21
23
  s.add_development_dependency 'rake', '~> 13.0'
22
24
  end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Corindon
4
+ module DependencyInjection
5
+ class Container
6
+ using Ext::Something
7
+
8
+ attr_reader :definitions
9
+ attr_reader :injector
10
+ attr_reader :services
11
+
12
+ def initialize
13
+ @services = {}
14
+ @definitions = {}
15
+
16
+ @injector = Injector.new(container: self)
17
+ end
18
+
19
+ # @param [Class] klass
20
+ def add_definition(klass, &block)
21
+ @definitions[to_id(klass)] = if injectable?(klass)
22
+ klass.definition
23
+ elsif block.sth?
24
+ Dsl.new(klass).exec(&block)
25
+ else
26
+ Definition.new(klass)
27
+ end
28
+ end
29
+
30
+ # @param [Class, #to_s] key
31
+ # @return [Boolean]
32
+ def has?(key)
33
+ @definitions.key?(to_id(key))
34
+ end
35
+
36
+ # @param [Class, #to_s] key
37
+ # @return [Object]
38
+ def get(key)
39
+ id = to_id(key)
40
+
41
+ if has?(key)
42
+ services.fetch(id) { build_service(id) }
43
+ elsif injectable?(key)
44
+ key.definition.build(injector)
45
+ else
46
+ raise StandardError.new("No service #{id}")
47
+ end
48
+ end
49
+
50
+ private
51
+
52
+ def build_service(id)
53
+ @definitions.fetch(id).build(injector).tap do |service|
54
+ @services[id] = service
55
+ end
56
+ end
57
+
58
+ def injectable?(klass)
59
+ klass.ancestors.include?(Injectable)
60
+ end
61
+
62
+ # @param [Class, #to_s] key
63
+ def to_id(key)
64
+ if key.is_a?(Class)
65
+ key.name
66
+ else
67
+ key.to_s
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'semantic'
4
+
5
+ module Corindon
6
+ module DependencyInjection
7
+ class Definition
8
+ attr_reader :klass
9
+ attr_reader :args
10
+ attr_reader :kwargs
11
+ attr_reader :calls
12
+
13
+ def initialize(klass, args = [], kwargs = {}, calls = [])
14
+ @klass = klass
15
+ @args = args
16
+ @kwargs = kwargs
17
+ @calls = calls
18
+ end
19
+
20
+ # @param [Injector] injector
21
+ # # @return [Object]
22
+ def build(injector)
23
+ object = do_call(klass, :new, *injector.resolve(args, kwargs))
24
+
25
+ calls.each do |(call, call_args, call_kwargs)|
26
+ do_call(object, call, *injector.resolve(call_args, call_kwargs))
27
+ end
28
+
29
+ object
30
+ end
31
+
32
+ private
33
+
34
+ if ::Semantic::Version.new(RUBY_VERSION).satisfies?(">= 2.7.0")
35
+ def do_call(obj, method, args, kwargs)
36
+ obj.send(method, *args, **kwargs)
37
+ end
38
+ else
39
+ def do_call(obj, method, args, kwargs)
40
+ if args.empty? && kwargs.empty?
41
+ obj.send(method)
42
+ elsif args.empty?
43
+ obj.send(method, **kwargs)
44
+ elsif kwargs.empty?
45
+ obj.send(method, *args)
46
+ else
47
+ obj.send(method, *args, **kwargs)
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Corindon
4
+ module DependencyInjection
5
+ class Dsl
6
+ # @param [Class] klass
7
+ def initialize(klass)
8
+ @klass = klass
9
+ @args = []
10
+ @kwargs = {}
11
+ @calls = []
12
+ end
13
+
14
+ # @return [Definition]
15
+ def exec(&block)
16
+ instance_exec(&block)
17
+
18
+ Definition.new(@klass, @args, @kwargs, @calls)
19
+ end
20
+
21
+ def args(*arguments, **kv_arguments)
22
+ @args = arguments
23
+ @kwargs = kv_arguments
24
+ end
25
+
26
+ # @param [String] name
27
+ def call(name, *arguments, **kv_arguments)
28
+ @calls << [name, arguments, kv_arguments]
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Corindon
4
+ module DependencyInjection
5
+ module Injectable
6
+ def definition
7
+ Definition.new(self)
8
+ end
9
+
10
+ refine Class do
11
+ def injectable(*args, **kwargs, &block)
12
+ include Injectable
13
+
14
+ define_singleton_method :definition do
15
+ if block.nil?
16
+ Definition.new(self, args, kwargs, [])
17
+ else
18
+ Dsl.new(self).exec(&block)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Corindon
4
+ module DependencyInjection
5
+ class Injector
6
+ attr_reader :container
7
+
8
+ # @param [Container] container
9
+ def initialize(container:)
10
+ @container = container
11
+ end
12
+
13
+ # @return [Array{Array, Hash}]
14
+ def resolve(args, kwargs)
15
+ [resolve_value(args), resolve_value(kwargs)]
16
+ end
17
+
18
+ private
19
+
20
+ def resolve_value(value)
21
+ if value.is_a?(Array)
22
+ value.map(&method(:resolve_value))
23
+ elsif value.is_a?(Hash)
24
+ value.transform_values(&method(:resolve_value))
25
+ else
26
+ container.get(value)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Corindon
4
- VERSION = "0.1.0"
4
+ VERSION = "0.2.0"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: corindon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rémi Piotaix
@@ -10,6 +10,20 @@ bindir: bin
10
10
  cert_chain: []
11
11
  date: 2020-09-06 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: semantic
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: zeitwerk
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -24,6 +38,20 @@ dependencies:
24
38
  - - "~>"
25
39
  - !ruby/object:Gem::Version
26
40
  version: '2.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
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'
27
55
  - !ruby/object:Gem::Dependency
28
56
  name: minitest
29
57
  requirement: !ruby/object:Gem::Requirement
@@ -60,6 +88,11 @@ extra_rdoc_files: []
60
88
  files:
61
89
  - corindon.gemspec
62
90
  - lib/corindon.rb
91
+ - lib/corindon/dependency_injection/container.rb
92
+ - lib/corindon/dependency_injection/definition.rb
93
+ - lib/corindon/dependency_injection/dsl.rb
94
+ - lib/corindon/dependency_injection/injectable.rb
95
+ - lib/corindon/dependency_injection/injector.rb
63
96
  - lib/corindon/ext/something.rb
64
97
  - lib/corindon/version.rb
65
98
  homepage: https://gitlab.com/piotaixr/corindon