Class: Harbor::Container
- Inherits:
-
Object
- Object
- Harbor::Container
- Defined in:
- lib/harbor/container.rb
Overview
Harbor::Container is an inversion of control container for simple dependency injection. For more information on dependency injection, see martinfowler.com/articles/injection.html.
Simple Example:
services = Harbor::Container.new
services.register("mailer", Harbor::Mailer)
class Controller
attr_accessor :mailer
end
services.register("Controller", Controller)
services.get("Controller") # => #<Controller: @mailer=#<Mailer>>
Defined Under Namespace
Classes: RegistrationTypeMismatchError, ServiceRegistration
Instance Method Summary collapse
-
#get(name, optional_properties = {}) ⇒ Object
Retrieve a service by name from the set of registered services, initializing any dependencies from the container, and optionally setting any additional properties on the service.
-
#initialize ⇒ Container
constructor
:nodoc:.
-
#register(name, service, &setup) ⇒ Object
Register a service by name, with an optional initializer block.
- #registered?(name) ⇒ Boolean
Constructor Details
#initialize ⇒ Container
:nodoc:
44 45 46 47 |
# File 'lib/harbor/container.rb', line 44 def initialize #:nodoc: @services = {} @dependencies = {} end |
Instance Method Details
#get(name, optional_properties = {}) ⇒ Object
Retrieve a service by name from the set of registered services, initializing any dependencies from the container, and optionally setting any additional properties on the service.
class Controller
attr_accessor :request, :response, :mailer
end
services.get("Controller", :request => Request.new(env), :response => Response.new(request))
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 |
# File 'lib/harbor/container.rb', line 60 def get(name, optional_properties = {}) raise ArgumentError.new("#{name} is not a registered service name") unless registered?(name) service_registration = @services[name] service = service_registration.service.is_a?(Class) ? service_registration.service.new : service_registration.service dependencies(name).each do |dependency| service.send("#{dependency}=", get(dependency, optional_properties)) end optional_instances = {} optional_properties.each_pair do |k,v| instance = v.is_a?(Class) ? v.new : v optional_instances[k] = instance end optional_instances.each_pair do |k, v| writer = "#{k}=" service.send(writer, v) if service.respond_to?(writer) optional_instances.each_pair do |k2,v2| next if k2 == k || !v2.respond_to?(writer) v2.send(writer, v) end end service_registration.initializers.each do |initializer| initializer.call(service) end service end |
#register(name, service, &setup) ⇒ Object
Register a service by name, with an optional initializer block.
services.register("mail_server", Harbor::SendmailServer.new(:sendmail => "/sbin/sendmail"))
services.register("mailer", Harbor::Mailer)
services.get("mailer") # => #<Harbor::Mailer @from=nil @mail_server=#<SendmailServer...>>
services.register("mailer", Harbor::Mailer) { |mailer| mailer.from = "[email protected]" }
services.get("mailer") # => #<Harbor::Mailer @from="[email protected]" @mail_server=#<SendmailServer...>>
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/harbor/container.rb', line 101 def register(name, service, &setup) if (existing_registration = @services[name]) && existing_registration.service != service raise RegistrationTypeMismatchError.new(name, existing_registration.service, service) end type_dependencies = dependencies(name) type_methods = service.is_a?(Class) ? service.instance_methods.grep(/\=$/) : [] @services.values.each do |service_registration| if service_registration.service.is_a?(Class) && service_registration.service.instance_methods.include?("#{name}=") dependencies(service_registration.name) << name end if type_methods.include?("#{service_registration.name}=") type_dependencies << service_registration.name end end @services[name] ||= ServiceRegistration.new(name, service) @services[name].initializers << setup if setup self end |
#registered?(name) ⇒ Boolean
125 126 127 |
# File 'lib/harbor/container.rb', line 125 def registered?(name) @services.key?(name) end |