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