Class: Dry::System::Components::Bootable

Inherits:
Object
  • Object
show all
Defined in:
lib/dry/system/components/bootable.rb

Overview

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.

Examples:

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

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

Constant Summary collapse

DEFAULT_FINALIZE =
proc {}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(identifier, options = {}, &block) ⇒ Bootable

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a new instance of Bootable.


69
70
71
72
73
74
75
76
# File 'lib/dry/system/components/bootable.rb', line 69

def initialize(identifier, options = {}, &block)
  @identifier = identifier
  @triggers = { before: Hash.new { |h, k| h[k] = [] }, after: Hash.new { |h, k| h[k] = [] } }
  @options = block ? options.merge(block: block) : options
  @namespace = options[:namespace]
  finalize = options[:finalize] || DEFAULT_FINALIZE
  instance_exec(&finalize)
end

Instance Attribute Details

#finalizeBootable (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Automatically called by the booter object after starting a component

Returns:


54
55
56
# File 'lib/dry/system/components/bootable.rb', line 54

def finalize
  @finalize
end

#identifierObject (readonly)


50
51
52
# File 'lib/dry/system/components/bootable.rb', line 50

def identifier
  @identifier
end

#namespaceObject (readonly)


66
67
68
# File 'lib/dry/system/components/bootable.rb', line 66

def namespace
  @namespace
end

#optionsObject (readonly)


58
59
60
# File 'lib/dry/system/components/bootable.rb', line 58

def options
  @options
end

#triggersObject (readonly)


62
63
64
# File 'lib/dry/system/components/bootable.rb', line 62

def triggers
  @triggers
end

Instance Method Details

#after(event, &block) ⇒ Bootable

Specify an after callback

Returns:


127
128
129
130
# File 'lib/dry/system/components/bootable.rb', line 127

def after(event, &block)
  triggers[:after][event] << block
  self
end

#before(event, &block) ⇒ Bootable

Specify a before callback

Returns:


117
118
119
120
# File 'lib/dry/system/components/bootable.rb', line 117

def before(event, &block)
  triggers[:before][event] << block
  self
end

#boot?TrueClass

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Return true

Returns:

  • (TrueClass)

234
235
236
# File 'lib/dry/system/components/bootable.rb', line 234

def boot?
  true
end

#boot_fileString

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Return path to component's boot file

Returns:

  • (String)

243
244
245
246
# File 'lib/dry/system/components/bootable.rb', line 243

def boot_file
  container_boot_files.
    detect { |path| Pathname(path).basename(RB_EXT).to_s == identifier.to_s }
end

#boot_pathString

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Return path to boot dir

Returns:

  • (String)

253
254
255
# File 'lib/dry/system/components/bootable.rb', line 253

def boot_path
  container.boot_path
end

#configDry::Struct

Return component's configuration

Returns:

  • (Dry::Struct)

161
162
163
164
165
166
167
# File 'lib/dry/system/components/bootable.rb', line 161

def config
  if @config
    @config
  else
    configure!
  end
end

#configure(&block) ⇒ Bootable

Configure a component

Returns:


137
138
139
# File 'lib/dry/system/components/bootable.rb', line 137

def configure(&block)
  @config_block = block
end

#containerDry::Struct

Return system's container used by this component

Returns:

  • (Dry::Struct)

183
184
185
# File 'lib/dry/system/components/bootable.rb', line 183

def container
  options.fetch(:container)
end

#container_boot_filesString

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Return all boot files defined under container's boot path

Returns:

  • (String)

262
263
264
# File 'lib/dry/system/components/bootable.rb', line 262

def container_boot_files
  Dir[container.boot_path.join("**/#{RB_GLOB}")]
end

#initBootable

Execute `init` step

Returns:


83
84
85
86
87
88
# File 'lib/dry/system/components/bootable.rb', line 83

def init
  trigger(:before, :init)
  lifecycle.(:init)
  trigger(:after, :init)
  self
end

#new(identifier, new_options = EMPTY_HASH) ⇒ Dry::Struct

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Return a new instance with updated name and options

Returns:

  • (Dry::Struct)

216
217
218
# File 'lib/dry/system/components/bootable.rb', line 216

def new(identifier, new_options = EMPTY_HASH)
  self.class.new(identifier, options.merge(new_options))
end

#settings(&block) ⇒ Bootable

Define configuration settings with keys and types

Returns:


146
147
148
149
150
151
152
153
154
# File 'lib/dry/system/components/bootable.rb', line 146

def settings(&block)
  if block
    @settings_block = block
  elsif @settings_block
    @settings = Settings::DSL.new(identifier, &@settings_block).call
  else
    @settings
  end
end

#startBootable

Execute `start` step

Returns:


95
96
97
98
99
100
# File 'lib/dry/system/components/bootable.rb', line 95

def start
  trigger(:before, :start)
  lifecycle.(:start)
  trigger(:after, :start)
  self
end

#statusesArray<Symbol>

Return a list of lifecycle steps that were executed

Returns:

  • (Array<Symbol>)

174
175
176
# File 'lib/dry/system/components/bootable.rb', line 174

def statuses
  lifecycle.statuses
end

#stopBootable

Execute `stop` step

Returns:


107
108
109
110
# File 'lib/dry/system/components/bootable.rb', line 107

def stop
  lifecycle.(:stop)
  self
end

#trigger(key, event) ⇒ Bootable

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Trigger a callback

Returns:


204
205
206
207
208
209
# File 'lib/dry/system/components/bootable.rb', line 204

def trigger(key, event)
  triggers[key][event].each do |fn|
    container.instance_exec(lifecycle.container, &fn)
  end
  self
end

#with(new_options) ⇒ Dry::Struct

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Return a new instance with updated options

Returns:

  • (Dry::Struct)

225
226
227
# File 'lib/dry/system/components/bootable.rb', line 225

def with(new_options)
  self.class.new(identifier, options.merge(new_options))
end