smart_inject 0.0.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.
Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/lib/smart_inject.rb +105 -0
  3. metadata +48 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 4d6bdfd2e40cc84906ab12e6e37eb7ae2db54be98ca5a18106a7d4de7cc47545
4
+ data.tar.gz: 757349ae540f1ffcfb5857814a79c8ed21906654790a81ed854b6f21fdb60b24
5
+ SHA512:
6
+ metadata.gz: 9dfe7e53fd252c9bd8f8c162422aac075106bcbc4275afae916b184e86935a00ec250c30e5e8c737f1d5d13c3b04aac91a5208b39c053cbc4a335d67bb9cbad3
7
+ data.tar.gz: 6d60f6f4a659038127c6c2888ecb354667521f49ae160f9e9a285e910b3e3f45d16f07256f0912b4bca0c9c80e9255424c5d620139034b75c34900ad1db3caad
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # SmartInject - Made DI deadly simple
5
+ #
6
+ # SmartInject is a minimalist, flexible and efficient dependency injection for
7
+ # Ruby.
8
+ #
9
+ # Here, no DSL, no complex machinery, no dynamic change on the object model.
10
+ # This is just a lightweight class that bring you DI using constructor, one of
11
+ # the most used method for DI. You can use it without constraint on your design.
12
+ #
13
+ # SmartInject can be used in isolation within your Gem just by applying standard
14
+ # ruby code: extend a class from SmartInject, and this is your new DI container.
15
+ #
16
+ # Feel free to see the code of SmartInject (very short), get the gem or
17
+ # copy-past the SmartInject class file into your project... There is no external
18
+ # dependency.
19
+ #
20
+ # SmartInject is intented to be under your control. No magic here.
21
+ #
22
+ class SmartInject
23
+ class SmartInjectError < StandardError; end
24
+
25
+ class ContainerError < SmartInjectError; end
26
+
27
+ class InjectionError < SmartInjectError; end
28
+
29
+ class << self
30
+ def services
31
+ @services ||= {}
32
+ end
33
+
34
+ def [](klass)
35
+ klass_name = klass.to_s
36
+
37
+ if @share_injections
38
+ service = running[klass_name]
39
+ return service if service
40
+ end
41
+
42
+ service = services.fetch(klass_name) { raise InjectionError, "service #{klass_name} unknown. Try to add #{name}.add(self) at the begining of #{klass_name} class." }
43
+ try_instanciate(service).tap do |instance|
44
+ running[klass_name] = instance if @share_injections
45
+ end
46
+ end
47
+
48
+ def remap(looked_klass, injected_klass)
49
+ (raise ContainerError, "the #{name} container is already started. No remap allowed") if frozen?
50
+ (raise ContainerError, "first argument must be a class. Found: #{looked_klass}") unless looked_klass.instance_of?(Class)
51
+ (raise ContainerError, "second argument must be a class. Found: #{injected_klass}") unless injected_klass.instance_of?(Class)
52
+
53
+ services[looked_klass.name] = injected_klass
54
+ self
55
+ end
56
+
57
+ def add(klass, &block)
58
+ (raise ContainerError, "the #{name} container is already started. No add allowed") if frozen?
59
+ (raise ContainerError, "first argument must be a class. Found: #{klass}") unless klass.instance_of?(Class)
60
+
61
+ services[klass.name] = block || klass
62
+ running.delete(klass.name)
63
+ self
64
+ end
65
+
66
+ def start_container!
67
+ return self if frozen?
68
+ return freeze if @share_injections
69
+
70
+ services.each do |(klass_name, service)|
71
+ next if running[klass_name]
72
+
73
+ try_instanciate(service).tap { |instance| running[klass_name] = instance }
74
+ end
75
+ freeze
76
+ end
77
+
78
+ def share_injections
79
+ (raise ContainerError, "the #{name} container is already started. No share_injections allowed") if frozen?
80
+
81
+ @share_injections = true
82
+ self
83
+ end
84
+
85
+ def share_injections?
86
+ !!(@share_injections)
87
+ end
88
+
89
+ private
90
+
91
+ def running
92
+ @running ||= {}
93
+ end
94
+
95
+ def try_instanciate(klass_or_callable)
96
+ if klass_or_callable.is_a?(Proc)
97
+ klass_or_callable.call
98
+ else
99
+ klass_or_callable.new
100
+ end
101
+ rescue ArgumentError
102
+ raise InjectionError, "automatic injection can't be done: all arguments of the constructor are not subject to injection. Try to #{name}.add(#{klass_or_callable}) { <BLOC TO INSTANTIATE YOUR CLASS WITH ARGUMENTS (OUTSIDE OF THOSE INJECTED)> }"
103
+ end
104
+ end
105
+ end
metadata ADDED
@@ -0,0 +1,48 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: smart_inject
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Ludovic de Luna
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-06-03 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: |
14
+ SmartInject is a minimalist, flexible and efficient dependency injection
15
+ for Ruby based on constructor injection, one of the most used method for
16
+ DI.
17
+
18
+ SmartInject is intented to be under your control. No magic here.
19
+ email: ludovic@deluna.fr
20
+ executables: []
21
+ extensions: []
22
+ extra_rdoc_files: []
23
+ files:
24
+ - lib/smart_inject.rb
25
+ homepage: https://rubygems.org/gems/smart_inject
26
+ licenses:
27
+ - MIT
28
+ metadata: {}
29
+ post_install_message:
30
+ rdoc_options: []
31
+ require_paths:
32
+ - lib
33
+ required_ruby_version: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - ">="
36
+ - !ruby/object:Gem::Version
37
+ version: '2.5'
38
+ required_rubygems_version: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ requirements: []
44
+ rubygems_version: 3.2.22
45
+ signing_key:
46
+ specification_version: 4
47
+ summary: Made DI deadly simple
48
+ test_files: []