Module | Dissident |
In: |
lib/nukumi2/vendor/dissident.rb
|
Dissident — a Ruby dependency injection container
Copyright (C) 2005 Christian Neukirchen <chneukirchen@gmail.com>
This work is licensed under the same terms as Ruby itself.
VERSION | = | "0.2" | ||
INJECTED | = | {} | A hash containing classes to inject in as keys. | |
LIBRARIES | = | {} | A hash mapping classes to the libraries they belong to. |
Return the declared dependencies of klass that are to be injected using Constructor Injection.
# File lib/nukumi2/vendor/dissident.rb, line 160 160: def constructor_parameters(klass) 161: if klass.const_defined? :DISSIDENT_CONSTRUCTOR 162: container = container_for klass 163: klass.const_get(:DISSIDENT_CONSTRUCTOR).map { |service| 164: container.fetch service 165: } 166: else 167: # By default, inject no constructor parameters. 168: [] 169: end 170: end
Set the global default container to default. Usually not needed, it is better style to use Dissident.with.
# File lib/nukumi2/vendor/dissident.rb, line 82 82: def container=(default) 83: Thread.main[:DISSIDENT_CONTAINER][nil] = if default.nil? 84: nil 85: else 86: Dissident.instantiate default 87: end 88: end
Return the container that will be used for injecting dependencies into objects of klass.
# File lib/nukumi2/vendor/dissident.rb, line 174 174: def container_for(klass) 175: copy_binding 176: Thread.current[:DISSIDENT_CONTAINER].fetch(library(klass)) 177: end
Inject all the dependencies of object.
# File lib/nukumi2/vendor/dissident.rb, line 143 143: def inject(object) 144: if object.class.ancestors.any? { |a| INJECTED[a] } 145: container = container_for object.class 146: 147: if container.nil? 148: warn "Dissident: Cannot inject to #{object} " << 149: "(#{library(object.class) || "default application"}), " << 150: "no container given." 151: else 152: object.instance_variable_set :@__dissident__, container 153: end 154: end 155: object 156: end
Instantiate object (a Dissident::Container) to be used for dependency injection.
# File lib/nukumi2/vendor/dissident.rb, line 92 92: def instantiate(object) 93: if object.kind_of? Class and object < Container 94: cont = object.new 95: cache = Cache.new(cont) 96: cont.cache = cache 97: else 98: raise ArgumentError, "#{object} is not a Dissident::Container" 99: end 100: end
Register klass to make use of Dissident.
This needs only to be explicitly called when you declare Constructor Injection with DISSIDENT_CONSTRUCTOR.
It is recommended to make use of provide instead of this.
# File lib/nukumi2/vendor/dissident.rb, line 138 138: def use_for(klass) 139: klass.use_dissident! 140: end
Make cont the current global container in block.
Optionally, pass a hash that maps libraries to the container used for them. Example:
Dissident.with MyGlobalContainer, MyFirstLib => FirstContainer, MySecondLib => SecondContainer do ... end
# File lib/nukumi2/vendor/dissident.rb, line 112 112: def with(cont, library = nil, &block) 113: if cont.kind_of? Hash or library.kind_of? Hash 114: if library.nil? 115: recurse cont, &block 116: else 117: with(cont) { recurse library, &block } 118: end 119: else 120: if block.nil? 121: raise ArgumentError, "Dissident.with must be called with a block" 122: end 123: 124: cont = instantiate cont 125: 126: fluid_let(library, cont) { 127: yield cont 128: } 129: end 130: end
# File lib/nukumi2/vendor/dissident.rb, line 216 216: def copy_binding 217: unless Thread.current.key? :DISSIDENT_CONTAINER 218: Thread.current[:DISSIDENT_CONTAINER] = 219: Thread.main[:DISSIDENT_CONTAINER].dup 220: end 221: end
# File lib/nukumi2/vendor/dissident.rb, line 203 203: def fluid_let(library, value, &block) 204: copy_binding 205: 206: old_value = Thread.current[:DISSIDENT_CONTAINER][library] 207: Thread.current[:DISSIDENT_CONTAINER][library] = value 208: 209: begin 210: block.call 211: ensure 212: Thread.current[:DISSIDENT_CONTAINER][library] = old_value 213: end 214: end
# File lib/nukumi2/vendor/dissident.rb, line 181 181: def library(klass) 182: LIBRARIES.fetch(klass) { 183: if klass.superclass 184: library klass.superclass 185: end 186: } 187: end
# File lib/nukumi2/vendor/dissident.rb, line 189 189: def recurse(rest, &block) 190: library = rest.keys.first 191: cont = rest.delete library 192: 193: # Zip down recursively. 194: if rest.empty? 195: with(cont, library, &block) 196: else 197: with(cont, library) { 198: with rest, &block 199: } 200: end 201: end