class Dry::System::Components::Bootable

Bootable components can provide one or more objects and typically depend on 3rd-party code. A typical bootable component can be a database library, or an API client.

These components can be registered via `Container.boot` and external component providers can register their components too, which then can be used and configured by your system.

@example simple logger

class App < Dry::System::Container
  boot(:logger) do
    init do
      require "logger"
    end

    start do
      register(:logger, Logger.new($stdout))
    end
  end
end

App[:logger] # returns configured logger

@example using built-in system components

class App < Dry::System::Container
  boot(:settings, from: :system) do
    settings do
      key :database_url, Types::String.constrained(filled: true)
      key :session_secret, Types::String.constrained(filled: true)
    end
  end
end

App[:settings] # returns loaded settings

@api public

Constants

DEFAULT_FINALIZE
TRIGGER_MAP

Attributes

name[R]

@!attribute [r] key

@return [Symbol] component's unique name
namespace[R]

@!attribute [r] namespace

@return [Symbol,String] default namespace for the container keys
options[R]

@!attribute [r] options

@return [Hash] component's options
triggers[R]

@!attribute [r] triggers

@return [Hash] lifecycle step after/before callbacks

Public Class Methods

new(name, options = {}, &block) click to toggle source

@api private

# File lib/dry/system/components/bootable.rb, line 69
def initialize(name, options = {}, &block)
  @config = nil
  @config_block = nil
  @name = name
  @triggers = {before: TRIGGER_MAP.dup, after: TRIGGER_MAP.dup}
  @options = block ? options.merge(block: block) : options
  @namespace = options[:namespace]
  finalize = options[:finalize] || DEFAULT_FINALIZE
  instance_exec(&finalize)
end

Public Instance Methods

after(event, &block) click to toggle source

Specify an after callback

@return [Bootable]

@api public

# File lib/dry/system/components/bootable.rb, line 129
def after(event, &block)
  triggers[:after][event] << block
  self
end
before(event, &block) click to toggle source

Specify a before callback

@return [Bootable]

@api public

# File lib/dry/system/components/bootable.rb, line 119
def before(event, &block)
  triggers[:before][event] << block
  self
end
config() click to toggle source

Return component's configuration

@return [Dry::Struct]

@api public

# File lib/dry/system/components/bootable.rb, line 163
def config
  @config || configure!
end
configure(&block) click to toggle source

Configure a component

@return [Bootable]

@api public

# File lib/dry/system/components/bootable.rb, line 139
def configure(&block)
  @config_block = block
end
container() click to toggle source

Return system's container used by this component

@return [Dry::Struct]

@api public

# File lib/dry/system/components/bootable.rb, line 181
def container
  options.fetch(:container)
end
finalize() click to toggle source

Automatically called by the booter object after starting a component

@return [Bootable]

@api private

# File lib/dry/system/components/bootable.rb, line 190
def finalize
  lifecycle.container.each do |key, item|
    container.register(key, item) unless container.registered?(key)
  end
  self
end
init() click to toggle source

Execute `init` step

@return [Bootable]

@api public

# File lib/dry/system/components/bootable.rb, line 85
def init
  trigger(:before, :init)
  lifecycle.(:init)
  trigger(:after, :init)
  self
end
new(name, new_options = EMPTY_HASH) click to toggle source

Return a new instance with updated name and options

@return [Dry::Struct]

@api private

# File lib/dry/system/components/bootable.rb, line 214
def new(name, new_options = EMPTY_HASH)
  self.class.new(name, options.merge(new_options))
end
settings(&block) click to toggle source

Define configuration settings with keys and types

@return [Bootable]

@api public

# File lib/dry/system/components/bootable.rb, line 148
def settings(&block)
  if block
    @settings_block = block
  elsif @settings_block
    @settings = Settings::DSL.new(&@settings_block).call
  else
    @settings
  end
end
start() click to toggle source

Execute `start` step

@return [Bootable]

@api public

# File lib/dry/system/components/bootable.rb, line 97
def start
  trigger(:before, :start)
  lifecycle.(:start)
  trigger(:after, :start)
  self
end
statuses() click to toggle source

Return a list of lifecycle steps that were executed

@return [Array<Symbol>]

@api public

# File lib/dry/system/components/bootable.rb, line 172
def statuses
  lifecycle.statuses
end
stop() click to toggle source

Execute `stop` step

@return [Bootable]

@api public

# File lib/dry/system/components/bootable.rb, line 109
def stop
  lifecycle.(:stop)
  self
end
trigger(key, event) click to toggle source

Trigger a callback

@return [Bootable]

@api private

# File lib/dry/system/components/bootable.rb, line 202
def trigger(key, event)
  triggers[key][event].each do |fn|
    container.instance_exec(lifecycle.container, &fn)
  end
  self
end
with(new_options) click to toggle source

Return a new instance with updated options

@return [Dry::Struct]

@api private

# File lib/dry/system/components/bootable.rb, line 223
def with(new_options)
  self.class.new(name, options.merge(new_options))
end

Private Instance Methods

block() click to toggle source

Return block that will be evaluated in the lifecycle context

@return [Proc]

@api private

# File lib/dry/system/components/bootable.rb, line 274
def block
  options.fetch(:block)
end
configure!() click to toggle source

Set config object

@return [Dry::Struct]

@api private

# File lib/dry/system/components/bootable.rb, line 265
def configure!
  @config = settings.new(Config.new(&@config_block)) if settings
end
lf_container() click to toggle source

Return configured container for the lifecycle object

@return [Dry::Container]

@api private

# File lib/dry/system/components/bootable.rb, line 243
        def lf_container
          container = Dry::Container.new

          case namespace
          when String, Symbol
            container.namespace(namespace) { |c| return c }
          when true
            container.namespace(name) { |c| return c }
          when nil
            container
          else
            raise <<-STR
              +namespace+ boot option must be true, string or symbol #{namespace.inspect} given.
            STR
          end
        end
lifecycle() click to toggle source

Return lifecycle object used for this component

@return [Lifecycle]

@api private

# File lib/dry/system/components/bootable.rb, line 234
def lifecycle
  @lifecycle ||= Lifecycle.new(lf_container, component: self, &block)
end