Class: Wirer::ConstructionSession
- Inherits:
-
Object
- Object
- Wirer::ConstructionSession
- Defined in:
- lib/wirer/construction_session.rb
Instance Attribute Summary collapse
-
#container ⇒ Object
readonly
Returns the value of attribute container.
Instance Method Summary collapse
- #construct_and_inject_setter_dependencies(factory, instance) ⇒ Object
- #construct_dependencies(dependencies) ⇒ Object
- #construct_dependency(dependency) ⇒ Object
- #construct_factory(factory, *args, &block_arg) ⇒ Object
- #construct_factory_with_args(factory, *args, &block_arg) ⇒ Object
- #construct_factory_without_args(factory) ⇒ Object
- #construct_with_constructor_dependencies(factory, *args, &block_arg) ⇒ Object
-
#construction_session ⇒ Object
N.B.
- #curry_factory_with_constructed_dependencies(factory) ⇒ Object
-
#initialize(container) ⇒ ConstructionSession
constructor
A new instance of ConstructionSession.
- #post_initialize(factories_instances) ⇒ Object
Constructor Details
#initialize(container) ⇒ ConstructionSession
Returns a new instance of ConstructionSession.
6 7 8 9 |
# File 'lib/wirer/construction_session.rb', line 6 def initialize(container) @construction_mutex = Mutex.new @container = container end |
Instance Attribute Details
#container ⇒ Object (readonly)
Returns the value of attribute container.
4 5 6 |
# File 'lib/wirer/construction_session.rb', line 4 def container @container end |
Instance Method Details
#construct_and_inject_setter_dependencies(factory, instance) ⇒ Object
111 112 113 114 115 116 |
# File 'lib/wirer/construction_session.rb', line 111 def construct_and_inject_setter_dependencies(factory, instance) setter_deps = construct_dependencies(factory.setter_dependencies(instance)) setter_deps.each do |dep_name, dep| factory.inject_dependency(instance, dep_name, dep) end end |
#construct_dependencies(dependencies) ⇒ Object
40 41 42 43 44 45 46 |
# File 'lib/wirer/construction_session.rb', line 40 def construct_dependencies(dependencies) result = {} dependencies.each do |arg_name, dependency| result[arg_name] = construct_dependency(dependency) end result end |
#construct_dependency(dependency) ⇒ Object
48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/wirer/construction_session.rb', line 48 def construct_dependency(dependency) dependency.match_factories(@container.factories) do |factory| if dependency.factory? if @container.singleton_factories_instances.has_key?(factory) raise Error, "Problem with :factory => true dependency: #{factory} was added to the container as a singleton, so only a singleton instance can be supplied, not a wrapped factory" end curry_factory_with_constructed_dependencies(factory) else construct_factory_without_args(factory) end end end |
#construct_factory(factory, *args, &block_arg) ⇒ Object
61 62 63 64 65 66 67 |
# File 'lib/wirer/construction_session.rb', line 61 def construct_factory(factory, *args, &block_arg) if args.empty? && !block_arg construct_factory_without_args(factory) else construct_factory_with_args(factory, *args, &block_arg) end end |
#construct_factory_with_args(factory, *args, &block_arg) ⇒ Object
88 89 90 91 92 |
# File 'lib/wirer/construction_session.rb', line 88 def construct_factory_with_args(factory, *args, &block_arg) result = construct_with_constructor_dependencies(factory, *args, &block_arg) @queued_for_phase_2.push([factory, result]) result end |
#construct_factory_without_args(factory) ⇒ Object
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/wirer/construction_session.rb', line 69 def construct_factory_without_args(factory) instance = @container.singleton_factories_instances[factory] and return instance if @phase_1_in_progress.include?(factory) cycle = @phase_1_in_progress[@phase_1_in_progress.index(factory)..-1] + [factory] raise CyclicDependencyError, "Cyclic constructor dependencies. Break the cycle by changing some into setter dependencies:\n#{cycle.map(&:inspect).join("\n")}" end @phase_1_in_progress.push(factory) result = construct_with_constructor_dependencies(factory) @phase_1_in_progress.pop if @container.singleton_factories_instances.has_key?(factory) @container.singleton_factories_instances[factory] = result end @queued_for_phase_2.push([factory, result]) result end |
#construct_with_constructor_dependencies(factory, *args, &block_arg) ⇒ Object
94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/wirer/construction_session.rb', line 94 def construct_with_constructor_dependencies(factory, *args, &block_arg) deps = construct_dependencies(factory.constructor_dependencies) begin factory.new_from_dependencies(deps, *args, &block_arg) rescue Wirer::Error raise rescue => e wrapped = DependencyConstructionError.new("Unable to construct factory: #{factory.inspect}", e) raise wrapped end end |
#construction_session ⇒ Object
N.B. all calls to the private construct_ methods below must be wrapped with this at the top-level entry point. It wraps with a mutex, to avoid race conditions with concurrent attempts to construct a singleton factory, and also ensures that everything constructed in this session gets post_initialized at the end.
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/wirer/construction_session.rb', line 16 def construction_session @construction_mutex.synchronize do begin @phase_1_in_progress = [] @queued_for_phase_2 = [] @queued_for_post_initialize = [] result = yield until @queued_for_phase_2.empty? factory_instance = @queued_for_phase_2.pop construct_and_inject_setter_dependencies(*factory_instance) @queued_for_post_initialize.push(factory_instance) end result ensure post_initialize(@queued_for_post_initialize) remove_instance_variable(:@phase_1_in_progress) remove_instance_variable(:@queued_for_post_initialize) end end end |
#curry_factory_with_constructed_dependencies(factory) ⇒ Object
106 107 108 109 |
# File 'lib/wirer/construction_session.rb', line 106 def curry_factory_with_constructed_dependencies(factory) deps = construct_dependencies(factory.constructor_dependencies) factory.curry_with_dependencies(deps, self) end |
#post_initialize(factories_instances) ⇒ Object
118 119 120 |
# File 'lib/wirer/construction_session.rb', line 118 def post_initialize(factories_instances) factories_instances.each {|factory, instance| factory.post_initialize(instance)} end |