Class: SenroUsecaser::Container
- Inherits:
-
Object
- Object
- SenroUsecaser::Container
- Defined in:
- lib/senro_usecaser/container.rb
Overview
DI Container with namespace support
Defined Under Namespace
Classes: DuplicateRegistrationError, ResolutionError
Instance Attribute Summary collapse
-
#parent ⇒ Object
readonly
Returns the parent container if any.
Instance Method Summary collapse
-
#clear! ⇒ Object
Clears all registrations.
-
#initialize(parent: nil) ⇒ Container
constructor
: (?parent: Container?) -> void.
-
#keys ⇒ Object
Returns all registered keys (including parent keys).
-
#namespace(name) ⇒ Object
Creates a namespace scope for registering dependencies.
-
#own_keys ⇒ Object
Returns only keys registered in this container (excluding parent).
-
#register(key, value = nil, &block) ⇒ Object
Registers a dependency in the current namespace.
-
#register_lazy(key, &block) ⇒ Object
Registers a lazy dependency (block is called every time on resolve).
-
#register_singleton(key, &block) ⇒ Object
Registers a singleton dependency (block is called once and cached).
-
#registered?(key) ⇒ Boolean
Checks if a dependency is registered.
-
#registered_in?(namespace, key) ⇒ Boolean
Checks if a dependency is registered in a specific namespace or its ancestors.
-
#resolve(key) ⇒ Object
Resolves a dependency from the current namespace or its ancestors.
-
#resolve_in(namespace, key) ⇒ Object
Resolves a dependency from a specific namespace or its ancestors.
-
#scope(&block) ⇒ Object
Creates a scoped child container that inherits from this container.
Constructor Details
#initialize(parent: nil) ⇒ Container
: (?parent: Container?) -> void
51 52 53 54 55 |
# File 'lib/senro_usecaser/container.rb', line 51 def initialize(parent: nil) @parent = parent @registrations = {} #: Hash[String, untyped] @current_namespace = [] #: Array[Symbol] end |
Instance Attribute Details
#parent ⇒ Object (readonly)
Returns the parent container if any
: () -> Container?
226 227 228 |
# File 'lib/senro_usecaser/container.rb', line 226 def parent @parent end |
Instance Method Details
#clear! ⇒ Object
Clears all registrations
: () -> void
231 232 233 |
# File 'lib/senro_usecaser/container.rb', line 231 def clear! @registrations.clear end |
#keys ⇒ Object
Returns all registered keys (including parent keys)
: () -> Array
209 210 211 212 213 214 |
# File 'lib/senro_usecaser/container.rb', line 209 def keys own_keys = @registrations.keys return own_keys unless @parent (own_keys + @parent.keys).uniq end |
#namespace(name) ⇒ Object
Creates a namespace scope for registering dependencies
: ((Symbol | String)) { () -> void } -> void
199 200 201 202 203 204 |
# File 'lib/senro_usecaser/container.rb', line 199 def namespace(name, &) @current_namespace.push(name.to_sym) instance_eval(&) # steep:ignore BlockTypeMismatch ensure @current_namespace.pop end |
#own_keys ⇒ Object
Returns only keys registered in this container (excluding parent)
: () -> Array
219 220 221 |
# File 'lib/senro_usecaser/container.rb', line 219 def own_keys @registrations.keys end |
#register(key, value = nil, &block) ⇒ Object
Registers a dependency in the current namespace
: (Symbol, ?untyped) ?{ (Container) -> untyped } -> void
82 83 84 85 86 87 88 89 90 |
# File 'lib/senro_usecaser/container.rb', line 82 def register(key, value = nil, &block) raise ArgumentError, "Provide either a value or a block, not both" if value && block raise ArgumentError, "Provide either a value or a block" if value.nil? && block.nil? full_key = build_key(key) check_duplicate_registration!(full_key) @registrations[full_key] = block || ->(_) { value } end |
#register_lazy(key, &block) ⇒ Object
Registers a lazy dependency (block is called every time on resolve)
: [T] (Symbol) { (Container) -> T } -> void
103 104 105 106 107 108 109 110 |
# File 'lib/senro_usecaser/container.rb', line 103 def register_lazy(key, &block) raise ArgumentError, "Block is required for register_lazy" unless block full_key = build_key(key) check_duplicate_registration!(full_key) @registrations[full_key] = block end |
#register_singleton(key, &block) ⇒ Object
Registers a singleton dependency (block is called once and cached)
: [T] (Symbol) { (Container) -> T } -> void
124 125 126 127 128 129 130 131 |
# File 'lib/senro_usecaser/container.rb', line 124 def register_singleton(key, &block) raise ArgumentError, "Block is required for register_singleton" unless block full_key = build_key(key) check_duplicate_registration!(full_key) @registrations[full_key] = SingletonRegistration.new(block) end |
#registered?(key) ⇒ Boolean
Checks if a dependency is registered
: (Symbol) -> bool
165 166 167 |
# File 'lib/senro_usecaser/container.rb', line 165 def registered?(key) registered_in?(current_namespace_path, key) end |
#registered_in?(namespace, key) ⇒ Boolean
Checks if a dependency is registered in a specific namespace or its ancestors
: ((Symbol | String | Array), Symbol) -> bool
172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
# File 'lib/senro_usecaser/container.rb', line 172 def registered_in?(namespace, key) namespace_parts = normalize_namespace(namespace) (namespace_parts.length + 1).times do |i| current_parts = namespace_parts[0, namespace_parts.length - i] || [] full_key = build_key_with_namespace(current_parts, key) return true if @registrations.key?(full_key) end # Check parent container if available return @parent.registered_in?(namespace, key) if @parent false end |
#resolve(key) ⇒ Object
Resolves a dependency from the current namespace or its ancestors
: [T] (Symbol) -> T
139 140 141 |
# File 'lib/senro_usecaser/container.rb', line 139 def resolve(key) resolve_in(current_namespace_path, key) end |
#resolve_in(namespace, key) ⇒ Object
Resolves a dependency from a specific namespace or its ancestors
: [T] ((Symbol | String | Array), Symbol) -> T
150 151 152 153 154 155 156 157 158 159 160 |
# File 'lib/senro_usecaser/container.rb', line 150 def resolve_in(namespace, key) registration = find_registration(namespace, key) unless registration raise ResolutionError, "Dependency #{key.inspect} not found in namespace #{namespace.inspect} or its ancestors" end # Always invoke with self (the resolving container) for proper scoping invoke_registration(registration) end |
#scope(&block) ⇒ Object
Creates a scoped child container that inherits from this container
: () ?{ () -> void } -> Container
67 68 69 70 71 |
# File 'lib/senro_usecaser/container.rb', line 67 def scope(&block) child = Container.new(parent: self) child.instance_eval(&block) if block # steep:ignore BlockTypeMismatch child end |