lib/dry/system/container.rb in dry-system-0.7.3 vs lib/dry/system/container.rb in dry-system-0.8.0
- old
+ new
@@ -4,10 +4,11 @@
require 'dry-configurable'
require 'dry-container'
require 'dry/core/deprecations'
+require 'dry/system'
require 'dry/system/errors'
require 'dry/system/loader'
require 'dry/system/booter'
require 'dry/system/auto_registrar'
require 'dry/system/manual_registrar'
@@ -75,10 +76,11 @@
setting :loader, Dry::System::Loader
setting :booter, Dry::System::Booter
setting :auto_registrar, Dry::System::AutoRegistrar
setting :manual_registrar, Dry::System::ManualRegistrar
setting :importer, Dry::System::Importer
+ setting(:components, {}, reader: true) { |v| v.dup }
class << self
extend Dry::Core::Deprecations['Dry::System::Container']
# Configures the container
@@ -152,20 +154,20 @@
# end
#
# # system/boot/db.rb
# #
# # Simple component registration
- # MyApp.finalize(:db) do |container|
+ # MyApp.boot(:db) do |container|
# require 'db'
#
# container.register(:db, DB.new)
# end
#
# # system/boot/db.rb
# #
# # Component registration with lifecycle triggers
- # MyApp.finalize(:db) do |container|
+ # MyApp.boot(:db) do |container|
# init do
# require 'db'
# DB.configure(ENV['DB_URL'])
# container.register(:db, DB.new)
# end
@@ -180,11 +182,11 @@
# end
#
# # system/boot/db.rb
# #
# # Component registration which uses another bootable component
- # MyApp.finalize(:db) do |container|
+ # MyApp.boot(:db) do |container|
# use :logger
#
# start do
# require 'db'
# DB.configure(ENV['DB_URL'], logger: logger)
@@ -207,15 +209,47 @@
# @see Lifecycle
#
# @return [self]
#
# @api public
- def finalize(name, &block)
- booter[name] = [self, block]
+ def boot(name, opts = {}, &block)
+ if components.key?(name)
+ raise DuplicatedComponentKeyError, "Bootable component #{name.inspect} was already registered"
+ end
+
+ component =
+ if opts[:from]
+ boot_external(name, opts, &block)
+ else
+ boot_local(name, opts, &block)
+ end
self
+
+ components[name] = component
end
+ deprecate :finalize, :boot
+ # @api private
+ def boot_external(identifier, from:, key: nil, namespace: nil, &block)
+ component = System.providers[from].component(
+ key || identifier, key: identifier, namespace: namespace, finalize: block, container: self
+ )
+
+ booter.register_component(component)
+
+ component
+ end
+
+ # @api private
+ def boot_local(name, namespace: nil, &block)
+ component = Components::Bootable.new(name, container: self, namespace: namespace, &block)
+
+ booter.register_component(component)
+
+ component
+ end
+
# Return if a container was finalized
#
# @return [TrueClass, FalseClass]
#
# @api public
@@ -281,11 +315,10 @@
# @api public
def start(name)
booter.start(name)
self
end
- deprecate :boot!, :start
# Boots a specific component but calls only `init` lifecycle trigger
#
# This way of booting is useful in places where a heavy dependency is
# needed but its started environment is not required
@@ -300,11 +333,10 @@
# @api public
def init(name)
booter.init(name)
self
end
- deprecate :boot, :init
# Sets load paths relative to the container's root dir
#
# @example
# class MyApp < Dry::System::Container
@@ -455,14 +487,19 @@
@load_paths ||= []
end
# @api private
def booter
- @booter ||= config.booter.new(root.join("#{config.system_dir}/boot"))
+ @booter ||= config.booter.new(boot_path)
end
# @api private
+ def boot_path
+ root.join("#{config.system_dir}/boot")
+ end
+
+ # @api private
def auto_registrar
@auto_registrar ||= config.auto_registrar.new(self)
end
# @api private
@@ -474,18 +511,22 @@
def importer
@importer ||= config.importer.new(self)
end
# @api private
- def component(key, **options)
- Component.new(
- key,
- loader: config.loader,
- namespace: config.default_namespace,
- separator: config.namespace_separator,
- **options,
- )
+ def component(identifier, **options)
+ if (component = booter.components.detect { |c| c.identifier == identifier })
+ component
+ else
+ Component.new(
+ identifier,
+ loader: config.loader,
+ namespace: config.default_namespace,
+ separator: config.namespace_separator,
+ **options,
+ )
+ end
end
# @api private
def require_component(component)
return if key?(component.identifier)
@@ -502,16 +543,22 @@
# @api private
def load_component(key)
return self if key?(key)
component(key).tap do |component|
- root_key = component.root_key
-
- if importer.key?(root_key)
- load_external_component(component.namespaced(root_key))
+ if component.boot?
+ booter.start(component)
else
- load_local_component(component)
+ root_key = component.root_key
+
+ if (bootable_dep = component(root_key)).boot?
+ booter.start(bootable_dep)
+ elsif importer.key?(root_key)
+ load_imported_component(component.namespaced(root_key))
+ else
+ load_local_component(component)
+ end
end
end
self
end
@@ -534,10 +581,10 @@
raise ComponentLoadError, component
end
end
# @api private
- def load_external_component(component)
+ def load_imported_component(component)
container = importer[component.namespace]
container.load_component(component.identifier)
importer.(component.namespace, container)
end
end