Module: Tina4::Container
- Defined in:
- lib/tina4/container.rb
Overview
Lightweight dependency injection container.
Tina4::Container.register(:mailer) { MailService.new } # transient — new instance each get
Tina4::Container.singleton(:db) { Database.new(ENV["DB_URL"]) } # singleton — memoised
Tina4::Container.register(:cache, RedisCacheInstance) # concrete instance (always same)
Tina4::Container.get(:db) # => Database instance
Class Method Summary collapse
-
.get(name) ⇒ Object
Resolve a service by name.
-
.has(name) ⇒ Object
Check if a service is registered.
-
.register(name, instance = nil, &factory) ⇒ Object
Register a service by name.
- .registry ⇒ Object
-
.reset ⇒ Object
Remove all registrations (useful in tests).
-
.singleton(name, &factory) ⇒ Object
Register a singleton factory by name.
Class Method Details
.get(name) ⇒ Object
Resolve a service by name. Singletons and concrete instances return the same object each time. Transient factories (register with block) return a new object each time.
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/tina4/container.rb', line 42 def get(name) entry = registry[name.to_sym] raise KeyError, "service not registered: #{name}" unless entry # Concrete instance (register with value) return entry[:instance] if entry[:instance] && entry[:factory].nil? if entry[:factory] if entry[:singleton] # Singleton — call once, memoize entry[:instance] ||= entry[:factory].call entry[:instance] else # Transient — call every time entry[:factory].call end else entry[:instance] end end |
.has(name) ⇒ Object
Check if a service is registered.
64 65 66 |
# File 'lib/tina4/container.rb', line 64 def has(name) registry.key?(name.to_sym) end |
.register(name, instance = nil, &factory) ⇒ Object
Register a service by name. Pass a concrete instance directly, or a block for transient instantiation. Blocks are called on every get() — use singleton() for memoised factories.
20 21 22 23 24 25 26 27 28 29 |
# File 'lib/tina4/container.rb', line 20 def register(name, instance = nil, &factory) raise ArgumentError, "provide an instance or a block, not both" if instance && factory raise ArgumentError, "provide an instance or a block" unless instance || factory registry[name.to_sym] = if factory { factory: factory, singleton: false, instance: nil } else { factory: nil, singleton: false, instance: instance } end end |
.registry ⇒ Object
13 14 15 |
# File 'lib/tina4/container.rb', line 13 def registry @registry ||= {} end |
.reset ⇒ Object
Remove all registrations (useful in tests).
69 70 71 |
# File 'lib/tina4/container.rb', line 69 def reset @registry = {} end |
.singleton(name, &factory) ⇒ Object
Register a singleton factory by name. The block is called once on first resolve() and the result is memoised.
33 34 35 36 37 |
# File 'lib/tina4/container.rb', line 33 def singleton(name, &factory) raise ArgumentError, "singleton requires a block" unless factory registry[name.to_sym] = { factory: factory, singleton: true, instance: nil } end |