-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathdependency_container.rb
91 lines (77 loc) · 1.95 KB
/
dependency_container.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
require "builders/specialist_document_builder"
class DependencyContainer
def initialize(&block)
@definitions = {}
instance_eval(&block) if block_given?
end
def define_factory(name, &block)
@definitions[name] = FactoryDependency.new(self, block)
end
def define_singleton(name, &block)
@definitions[name] = SingletonDependency.new(self, block)
end
def define_instance(name, instance = nil)
instance = yield if block_given?
@definitions[name] = InstanceDependency.new(self, instance)
end
def get(name)
definition(name).get
end
def dependency_defined?(name)
@definitions.has_key?(name)
end
def definition(name)
@definitions[name] || raise("Missing dependency #{name}")
end
def inject_into(klass, visibility: :private)
@definitions.each do |name, dependency|
unless klass.method_defined?(name)
klass.send(:define_method, name) { dependency.get }
klass.send(visibility, name)
end
end
end
protected
def dependencies_for(klass)
if klass.respond_to?(:members)
klass.members.map do |member|
get(member)
end
else
initializer_parameters = begin
klass.instance_method(:initialize).parameters
rescue NameError
[]
end
initializer_parameters.map do |(arg_type, arg_name)|
case arg_type
when :req
get(arg_name)
when :opt
get(arg_name) if dependency_defined?(arg_name)
when :rest
when :key
when :keyrest
end
end
end
end
def build_with_dependencies(klass)
klass.new(*dependencies_for(klass))
end
FactoryDependency = Struct.new(:container, :callable) do
def get
container.instance_eval(&callable)
end
end
class SingletonDependency < FactoryDependency
def get
@instance ||= super
end
end
InstanceDependency = Struct.new(:container, :instance) do
def get
self.instance
end
end
end