Class: Dim::Container
- Inherits:
-
Object
- Object
- Dim::Container
- Defined in:
- lib/dim.rb
Overview
Dim::Container is the central data store for registering services used for dependency injuction. Users register services by providing a name and a block used to create the service. Services may be retrieved by asking for them by name (via the [] operator) or by selector (via the method_missing technique).
Instance Attribute Summary collapse
-
#parent ⇒ Object
readonly
Returns the value of attribute parent.
Class Method Summary collapse
-
.service_block(name) ⇒ Object
Searching for a service block only reaches the Container class when all the containers in the hierarchy search chain have no entry for the service.
Instance Method Summary collapse
-
#[](name) ⇒ Object
Lookup a service by name.
-
#clear_cache! ⇒ Object
Resets the cached services.
-
#initialize(parent = nil) ⇒ Container
constructor
Create a dependency injection container.
-
#method_missing(sym, *args, &block) ⇒ Object
Lookup a service by message selector.
- #override(name, &block) ⇒ Object
-
#register(name, raise_error_on_duplicate = true, &block) ⇒ Object
Register a service named
name
. -
#register_env(name, default = nil) ⇒ Object
Lookup a service from ENV variables, or use a default if given; fall back to searching the container and its parents for a default value.
-
#service_block(name) ⇒ Object
Return the block that creates the named service.
-
#service_exists?(name) ⇒ Boolean
Check to see if a custom method or service has been registered, returning true or false.
-
#verify_dependencies(*names) ⇒ Object
Given a list of services, check to see if they are available, returning true or false.
-
#verify_dependencies!(*names) ⇒ Object
Given a list of services, check to see if they are available or raise an exception.
Constructor Details
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(sym, *args, &block) ⇒ Object
Lookup a service by message selector. A service with the same name as sym
will be returned, or an exception is thrown if no matching service is found.
104 105 106 |
# File 'lib/dim.rb', line 104 def method_missing(sym, *args, &block) self[sym] end |
Instance Attribute Details
#parent ⇒ Object (readonly)
Returns the value of attribute parent.
47 48 49 |
# File 'lib/dim.rb', line 47 def parent @parent end |
Class Method Details
.service_block(name) ⇒ Object
Searching for a service block only reaches the Container class when all the containers in the hierarchy search chain have no entry for the service. In this case, the only thing to do is signal a failure.
124 125 126 |
# File 'lib/dim.rb', line 124 def self.service_block(name) fail(MissingServiceError, "Unknown Service '#{name}'") end |
Instance Method Details
#[](name) ⇒ Object
Lookup a service by name. Throw an exception if no service is found.
97 98 99 |
# File 'lib/dim.rb', line 97 def [](name) @cache[name] ||= service_block(name).call(self) end |
#clear_cache! ⇒ Object
Resets the cached services
116 117 118 |
# File 'lib/dim.rb', line 116 def clear_cache! @cache = {} end |
#override(name, &block) ⇒ Object
76 77 78 |
# File 'lib/dim.rb', line 76 def override(name,&block) register(name,false,&block) end |
#register(name, raise_error_on_duplicate = true, &block) ⇒ Object
Register a service named name
. The block
will be used to create the service on demand. It is recommended that symbols be used as the name of a service.
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/dim.rb', line 60 def register(name,raise_error_on_duplicate = true,&block) if @services[name] if raise_error_on_duplicate fail DuplicateServiceError, "Duplicate Service Name '#{name}'" else # delete the service from the cache @cache.delete(name) end end @services[name] = block self.class.send(:define_method, name) do self[name] end end |
#register_env(name, default = nil) ⇒ Object
Lookup a service from ENV variables, or use a default if given; fall back to searching the container and its parents for a default value
81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/dim.rb', line 81 def register_env(name,default = nil) if value = ENV[name.to_s.upcase] register(name) { value } elsif default register(name) { default } else begin @parent.service_block(name) rescue MissingServiceError raise EnvironmentVariableNotFound, "Could not find an ENV variable named '#{name.to_s.upcase}' nor could we find a service named #{name} in the parent container" end end end |
#service_block(name) ⇒ Object
Return the block that creates the named service. Throw an exception if no service creation block of the given name can be found in the container or its parents.
111 112 113 |
# File 'lib/dim.rb', line 111 def service_block(name) @services[name] || @parent.service_block(name) end |
#service_exists?(name) ⇒ Boolean
Check to see if a custom method or service has been registered, returning true or false.
129 130 131 132 133 |
# File 'lib/dim.rb', line 129 def service_exists?(name) respond_to?(name) || service_block(name) rescue Dim::MissingServiceError false end |
#verify_dependencies(*names) ⇒ Object
Given a list of services, check to see if they are available, returning true or false.
136 137 138 |
# File 'lib/dim.rb', line 136 def verify_dependencies(*names) names.all? { |name| service_exists?(name) } end |
#verify_dependencies!(*names) ⇒ Object
Given a list of services, check to see if they are available or raise an exception.
141 142 143 144 145 146 147 |
# File 'lib/dim.rb', line 141 def verify_dependencies!(*names) missing_dependencies = names.reject { |name| service_exists?(name) } unless missing_dependencies.empty? fail Dim::MissingServiceError, "Missing dependencies #{missing_dependencies.join(", ")}" end end |