dry-system 0.7.3 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +17 -0
- data/lib/dry/system.rb +24 -0
- data/lib/dry/system/booter.rb +75 -43
- data/lib/dry/system/booter/component_registry.rb +37 -0
- data/lib/dry/system/component.rb +9 -4
- data/lib/dry/system/components.rb +6 -0
- data/lib/dry/system/components/bootable.rb +307 -0
- data/lib/dry/system/components/config.rb +33 -0
- data/lib/dry/system/constants.rb +2 -0
- data/lib/dry/system/container.rb +69 -22
- data/lib/dry/system/errors.rb +2 -2
- data/lib/dry/system/lifecycle.rb +40 -7
- data/lib/dry/system/provider.rb +46 -0
- data/lib/dry/system/provider_registry.rb +25 -0
- data/lib/dry/system/settings.rb +59 -0
- data/lib/dry/system/settings/file_loader.rb +28 -0
- data/lib/dry/system/settings/file_parser.rb +49 -0
- data/lib/dry/system/system_components/settings.rb +9 -0
- data/lib/dry/system/version.rb +1 -1
- metadata +27 -144
- data/.gitignore +0 -39
- data/.rspec +0 -3
- data/.travis.yml +0 -22
- data/.yardopts +0 -5
- data/CONTRIBUTING.md +0 -29
- data/Gemfile +0 -9
- data/Rakefile +0 -12
- data/dry-system.gemspec +0 -31
- data/examples/custom_configuration_auto_register/Gemfile +0 -5
- data/examples/custom_configuration_auto_register/lib/entities/user.rb +0 -7
- data/examples/custom_configuration_auto_register/lib/user_repo.rb +0 -5
- data/examples/custom_configuration_auto_register/run.rb +0 -8
- data/examples/custom_configuration_auto_register/system/boot/persistence.rb +0 -13
- data/examples/custom_configuration_auto_register/system/container.rb +0 -16
- data/examples/custom_configuration_auto_register/system/import.rb +0 -3
- data/examples/standalone/Gemfile +0 -5
- data/examples/standalone/lib/user_repo.rb +0 -5
- data/examples/standalone/run.rb +0 -8
- data/examples/standalone/system/boot/persistence.rb +0 -13
- data/examples/standalone/system/container.rb +0 -9
- data/examples/standalone/system/import.rb +0 -3
- data/spec/fixtures/components/bar.rb +0 -5
- data/spec/fixtures/components/bar/baz.rb +0 -4
- data/spec/fixtures/components/foo.rb +0 -2
- data/spec/fixtures/components/no_register.rb +0 -4
- data/spec/fixtures/import_test/config/application.yml +0 -2
- data/spec/fixtures/import_test/lib/test/bar.rb +0 -4
- data/spec/fixtures/import_test/lib/test/foo.rb +0 -5
- data/spec/fixtures/import_test/system/boot/bar.rb +0 -11
- data/spec/fixtures/lazytest/config/application.yml +0 -2
- data/spec/fixtures/lazytest/lib/test/dep.rb +0 -4
- data/spec/fixtures/lazytest/lib/test/foo.rb +0 -5
- data/spec/fixtures/lazytest/lib/test/models.rb +0 -4
- data/spec/fixtures/lazytest/lib/test/models/book.rb +0 -6
- data/spec/fixtures/lazytest/lib/test/models/user.rb +0 -6
- data/spec/fixtures/lazytest/system/boot/bar.rb +0 -15
- data/spec/fixtures/magic_comments/comments.rb +0 -17
- data/spec/fixtures/manual_registration/container/foo.rb +0 -6
- data/spec/fixtures/manual_registration/lib/test/foo.rb +0 -9
- data/spec/fixtures/multiple_namespaced_components/multiple/level/baz.rb +0 -7
- data/spec/fixtures/multiple_namespaced_components/multiple/level/foz.rb +0 -6
- data/spec/fixtures/namespaced_components/namespaced/bar.rb +0 -5
- data/spec/fixtures/namespaced_components/namespaced/foo.rb +0 -4
- data/spec/fixtures/other/config/boot/bar.rb +0 -11
- data/spec/fixtures/other/config/boot/hell.rb +0 -3
- data/spec/fixtures/other/lib/test/dep.rb +0 -4
- data/spec/fixtures/other/lib/test/foo.rb +0 -5
- data/spec/fixtures/other/lib/test/models.rb +0 -4
- data/spec/fixtures/other/lib/test/models/book.rb +0 -6
- data/spec/fixtures/other/lib/test/models/user.rb +0 -6
- data/spec/fixtures/stubbing/lib/test/car.rb +0 -7
- data/spec/fixtures/stubbing/system/boot/db.rb +0 -8
- data/spec/fixtures/test/config/application.yml +0 -2
- data/spec/fixtures/test/config/subapp.yml +0 -2
- data/spec/fixtures/test/lib/test/dep.rb +0 -4
- data/spec/fixtures/test/lib/test/foo.rb +0 -5
- data/spec/fixtures/test/lib/test/models.rb +0 -4
- data/spec/fixtures/test/lib/test/models/book.rb +0 -6
- data/spec/fixtures/test/lib/test/models/user.rb +0 -6
- data/spec/fixtures/test/lib/test/singleton_dep.rb +0 -7
- data/spec/fixtures/test/log/.gitkeep +0 -0
- data/spec/fixtures/test/system/boot/bar.rb +0 -11
- data/spec/fixtures/test/system/boot/client.rb +0 -7
- data/spec/fixtures/test/system/boot/db.rb +0 -1
- data/spec/fixtures/test/system/boot/hell.rb +0 -3
- data/spec/fixtures/test/system/boot/logger.rb +0 -5
- data/spec/fixtures/umbrella/system/boot/db.rb +0 -10
- data/spec/integration/boot_spec.rb +0 -18
- data/spec/integration/container/lazy_loading/manual_registration_spec.rb +0 -18
- data/spec/integration/import_spec.rb +0 -81
- data/spec/spec_helper.rb +0 -48
- data/spec/unit/auto_registrar/configuration_spec.rb +0 -26
- data/spec/unit/component_spec.rb +0 -121
- data/spec/unit/container/auto_register_spec.rb +0 -113
- data/spec/unit/container/config_spec.rb +0 -38
- data/spec/unit/container/finalize_spec.rb +0 -97
- data/spec/unit/container/import_spec.rb +0 -53
- data/spec/unit/container/injector_spec.rb +0 -29
- data/spec/unit/container_spec.rb +0 -244
- data/spec/unit/loader_spec.rb +0 -64
- data/spec/unit/magic_comments_parser_spec.rb +0 -41
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e2b3c4fc9aed09b6920d6c285df0407e8cb506f2
|
4
|
+
data.tar.gz: 5034704e210f09cae4f54e7ddb67371fc31bba31
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cff3f64d9fe0762d3e59893caf4f8e7f85da8b17ed40f7b6970a4518950e1ab60ad99531ae20383c10915ed296895df21a149f872a3d8dc0da214f7ed5caeabc
|
7
|
+
data.tar.gz: 51092e33d452c9008ddba0a384a989420287c9fce19f730b85f5903a99f7da5f4b4aa626ee4c83d693434135f8793b33aea7df037682b408f8fcfe1b751a3e00
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,20 @@
|
|
1
|
+
# 0.8.0 - 2017-10-16
|
2
|
+
|
3
|
+
### Added
|
4
|
+
|
5
|
+
* Support for external bootable components (solnic)
|
6
|
+
* Built-in `:system` components including `:settings` component (solnic)
|
7
|
+
|
8
|
+
### Fixed
|
9
|
+
|
10
|
+
* Lazy-loading components work when a container has `default_namespace` configured (GustavoCaso)
|
11
|
+
|
12
|
+
### Changed
|
13
|
+
|
14
|
+
* [BREAKING] Improved boot DSL with support for namespacing and lifecycle before/after callbacks (solnic)
|
15
|
+
|
16
|
+
[Compare v0.7.3...v0.8.0](https://github.com/dry-rb/dry-system/compare/v0.7.3...v0.8.0)
|
17
|
+
|
1
18
|
# 0.7.3 - 2017-08-02
|
2
19
|
|
3
20
|
### Fixed
|
data/lib/dry/system.rb
CHANGED
@@ -1,4 +1,28 @@
|
|
1
|
+
require 'dry/system/provider'
|
2
|
+
require 'dry/system/provider_registry'
|
3
|
+
|
1
4
|
module Dry
|
2
5
|
module System
|
6
|
+
# Register external component provider
|
7
|
+
#
|
8
|
+
# @api public
|
9
|
+
def self.register_provider(identifier, options)
|
10
|
+
providers.register(identifier, options)
|
11
|
+
providers[identifier].load_components
|
12
|
+
self
|
13
|
+
end
|
14
|
+
|
15
|
+
# Register an external component that can be booted within other systems
|
16
|
+
#
|
17
|
+
# @api public
|
18
|
+
def self.register_component(identifier, provider:, &block)
|
19
|
+
providers[provider].register_component(identifier, block)
|
20
|
+
self
|
21
|
+
end
|
22
|
+
|
23
|
+
# @api private
|
24
|
+
def self.providers
|
25
|
+
@__providers__ ||= ProviderRegistry.new
|
26
|
+
end
|
3
27
|
end
|
4
28
|
end
|
data/lib/dry/system/booter.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
+
require 'dry/system/components/bootable'
|
1
2
|
require 'dry/system/errors'
|
2
3
|
require 'dry/system/lifecycle'
|
4
|
+
require 'dry/system/booter/component_registry'
|
3
5
|
|
4
6
|
module Dry
|
5
7
|
module System
|
@@ -13,93 +15,123 @@ module Dry
|
|
13
15
|
class Booter
|
14
16
|
attr_reader :path
|
15
17
|
|
16
|
-
attr_reader :finalizers
|
17
|
-
|
18
18
|
attr_reader :booted
|
19
19
|
|
20
|
+
attr_reader :components
|
21
|
+
|
20
22
|
# @api private
|
21
23
|
def initialize(path)
|
22
24
|
@path = path
|
23
|
-
@booted =
|
24
|
-
@
|
25
|
+
@booted = []
|
26
|
+
@components = ComponentRegistry.new
|
25
27
|
end
|
26
28
|
|
27
29
|
# @api private
|
28
|
-
def
|
29
|
-
|
30
|
+
def register_component(component)
|
31
|
+
components.register(component)
|
30
32
|
self
|
31
33
|
end
|
32
34
|
|
33
35
|
# @api private
|
34
|
-
def
|
35
|
-
|
36
|
-
|
36
|
+
def load_component(path)
|
37
|
+
identifier = Pathname(path).basename('.rb').to_s.to_sym
|
38
|
+
|
39
|
+
unless components.exists?(identifier)
|
40
|
+
require path
|
37
41
|
end
|
38
|
-
|
42
|
+
|
43
|
+
self
|
39
44
|
end
|
40
45
|
|
41
46
|
# @api private
|
42
|
-
def
|
43
|
-
|
47
|
+
def finalize!
|
48
|
+
boot_files.each do |path|
|
49
|
+
load_component(path)
|
50
|
+
end
|
44
51
|
|
45
|
-
|
46
|
-
|
47
|
-
yield(lifecycle) if block_given?
|
52
|
+
components.each do |component|
|
53
|
+
start(component)
|
48
54
|
end
|
49
55
|
|
50
|
-
|
56
|
+
freeze
|
51
57
|
end
|
52
58
|
|
53
59
|
# @api private
|
54
|
-
def
|
55
|
-
|
60
|
+
def init(name_or_component)
|
61
|
+
with_component(name_or_component) do |component|
|
62
|
+
call(component) do
|
63
|
+
component.init
|
64
|
+
yield if block_given?
|
65
|
+
end
|
66
|
+
|
67
|
+
self
|
68
|
+
end
|
69
|
+
end
|
56
70
|
|
57
|
-
|
71
|
+
# @api private
|
72
|
+
def start(name_or_component)
|
73
|
+
with_component(name_or_component) do |component|
|
74
|
+
return self if booted.include?(component)
|
58
75
|
|
59
|
-
|
60
|
-
|
76
|
+
init(name_or_component) do
|
77
|
+
component.start
|
78
|
+
end
|
61
79
|
|
62
|
-
|
80
|
+
booted << component.finalize
|
81
|
+
|
82
|
+
self
|
83
|
+
end
|
63
84
|
end
|
64
85
|
|
65
86
|
# @api private
|
66
|
-
def call(
|
67
|
-
|
87
|
+
def call(name_or_component)
|
88
|
+
with_component(name_or_component) do |component|
|
89
|
+
unless component
|
90
|
+
raise ComponentFileMismatchError.new(name, registered_booted_keys)
|
91
|
+
end
|
68
92
|
|
69
|
-
|
93
|
+
yield(component) if block_given?
|
70
94
|
|
71
|
-
|
72
|
-
|
73
|
-
lifecycle
|
95
|
+
component
|
96
|
+
end
|
74
97
|
end
|
75
98
|
|
76
99
|
# @api private
|
77
|
-
def
|
78
|
-
|
79
|
-
start(boot_file.basename('.*').to_s.to_sym) if boot_file.exist?
|
100
|
+
def lifecycle_container(container)
|
101
|
+
LifecycleContainer.new(container)
|
80
102
|
end
|
81
103
|
|
82
|
-
private
|
104
|
+
# @api private
|
105
|
+
def with_component(id_or_component)
|
106
|
+
component =
|
107
|
+
case id_or_component
|
108
|
+
when Symbol
|
109
|
+
require_boot_file(id_or_component) unless components.exists?(id_or_component)
|
110
|
+
components[id_or_component]
|
111
|
+
when Components::Bootable
|
112
|
+
id_or_component
|
113
|
+
end
|
114
|
+
|
115
|
+
raise InvalidComponentError, id_or_component unless component
|
116
|
+
|
117
|
+
yield(component)
|
118
|
+
end
|
83
119
|
|
84
120
|
# @api private
|
85
|
-
def
|
86
|
-
|
121
|
+
def require_boot_file(identifier)
|
122
|
+
boot_file = boot_files.detect { |path| Pathname(path).basename('.rb').to_s == identifier.to_s }
|
123
|
+
require boot_file if boot_file
|
87
124
|
end
|
88
125
|
|
89
126
|
# @api private
|
90
127
|
def boot_files
|
91
|
-
path
|
128
|
+
Dir["#{path}/**/*.rb"]
|
92
129
|
end
|
93
130
|
|
94
131
|
# @api private
|
95
|
-
def
|
96
|
-
|
97
|
-
|
98
|
-
end
|
99
|
-
|
100
|
-
unless path.join("#{name}.rb").exist?
|
101
|
-
raise InvalidComponentIdentifierError, name
|
102
|
-
end
|
132
|
+
def boot_dependency(component)
|
133
|
+
boot_file = component.boot_file(path)
|
134
|
+
start(boot_file.basename('.*').to_s.to_sym) if boot_file.exist?
|
103
135
|
end
|
104
136
|
end
|
105
137
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Dry
|
2
|
+
module System
|
3
|
+
class Booter
|
4
|
+
class ComponentRegistry
|
5
|
+
include Enumerable
|
6
|
+
|
7
|
+
attr_reader :components
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@components = []
|
11
|
+
end
|
12
|
+
|
13
|
+
def each(&block)
|
14
|
+
components.each(&block)
|
15
|
+
end
|
16
|
+
|
17
|
+
def register(component)
|
18
|
+
@components << component
|
19
|
+
end
|
20
|
+
|
21
|
+
def exists?(name)
|
22
|
+
components.any? { |component| component.identifier == name }
|
23
|
+
end
|
24
|
+
|
25
|
+
def [](name)
|
26
|
+
component = components.detect { |component| component.identifier == name }
|
27
|
+
|
28
|
+
if component
|
29
|
+
component
|
30
|
+
else
|
31
|
+
raise InvalidComponentIdentifierError, name
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/dry/system/component.rb
CHANGED
@@ -41,8 +41,8 @@ module Dry
|
|
41
41
|
attr_reader :loader
|
42
42
|
|
43
43
|
# @api private
|
44
|
-
def self.new(*args)
|
45
|
-
cache.fetch_or_store(args.hash) do
|
44
|
+
def self.new(*args, &block)
|
45
|
+
cache.fetch_or_store([*args, block].hash) do
|
46
46
|
name, options = args
|
47
47
|
options = DEFAULT_OPTIONS.merge(options || {})
|
48
48
|
|
@@ -67,8 +67,8 @@ module Dry
|
|
67
67
|
# @api private
|
68
68
|
def self.remove_namespace_from_path(name, ns)
|
69
69
|
match_value = name.match(/^(?<remove_namespace>#{ns}).(?<identifier>.*)/)
|
70
|
-
|
71
|
-
match_value[:identifier]
|
70
|
+
|
71
|
+
match_value ? match_value[:identifier] : name
|
72
72
|
end
|
73
73
|
|
74
74
|
# @api private
|
@@ -108,6 +108,11 @@ module Dry
|
|
108
108
|
loader.call(*args)
|
109
109
|
end
|
110
110
|
|
111
|
+
# @api private
|
112
|
+
def boot?
|
113
|
+
false
|
114
|
+
end
|
115
|
+
|
111
116
|
# @api private
|
112
117
|
def bootable?(path)
|
113
118
|
boot_file(path).exist?
|
@@ -0,0 +1,307 @@
|
|
1
|
+
require 'dry/system/lifecycle'
|
2
|
+
require 'dry/system/settings'
|
3
|
+
require 'dry/system/components/config'
|
4
|
+
|
5
|
+
module Dry
|
6
|
+
module System
|
7
|
+
module Components
|
8
|
+
# Bootable components can provide one or more objects and typically depend
|
9
|
+
# on 3rd-party code. A typical bootable component can be a database library,
|
10
|
+
# or an API client.
|
11
|
+
#
|
12
|
+
# These components can be registered via `Container.boot` and external component
|
13
|
+
# providers can register their components too, which then can be used and configured
|
14
|
+
# by your system.
|
15
|
+
#
|
16
|
+
# @example simple logger
|
17
|
+
# class App < Dry::System::Container
|
18
|
+
# boot(:logger) do
|
19
|
+
# init do
|
20
|
+
# require "logger"
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# start do
|
24
|
+
# register(:logger, Logger.new($stdout))
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# App[:logger] # returns configured logger
|
30
|
+
#
|
31
|
+
# @example using built-in system components
|
32
|
+
# class App < Dry::System::Container
|
33
|
+
# boot(:settings, from: :system) do
|
34
|
+
# settings do
|
35
|
+
# key :database_url, Types::String.constrained(filled: true)
|
36
|
+
# key :session_secret, Types::String.constrained(filled: true)
|
37
|
+
# end
|
38
|
+
# end
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# App[:settings] # returns loaded settings
|
42
|
+
#
|
43
|
+
# @api public
|
44
|
+
class Bootable
|
45
|
+
DEFAULT_FINALIZE = proc {}
|
46
|
+
|
47
|
+
# @!attribute [r] identifier
|
48
|
+
# @return [Symbol] component's unique identifier
|
49
|
+
attr_reader :identifier
|
50
|
+
|
51
|
+
# @!attribute [r] finalize
|
52
|
+
# @return [Proc] Finalization proc
|
53
|
+
attr_reader :finalize
|
54
|
+
|
55
|
+
# @!attribute [r] options
|
56
|
+
# @return [Hash] component's options
|
57
|
+
attr_reader :options
|
58
|
+
|
59
|
+
# @!attribute [r] triggers
|
60
|
+
# @return [Hash] lifecycle step after/before callbacks
|
61
|
+
attr_reader :triggers
|
62
|
+
|
63
|
+
# @!attribute [r] namespace
|
64
|
+
# @return [Symbol,String] default namespace for the container keys
|
65
|
+
attr_reader :namespace
|
66
|
+
|
67
|
+
# @api private
|
68
|
+
def initialize(identifier, options = {}, &block)
|
69
|
+
@identifier = identifier
|
70
|
+
@triggers = { before: Hash.new { |h, k| h[k] = [] }, after: Hash.new { |h, k| h[k] = [] } }
|
71
|
+
@options = block ? options.merge(block: block) : options
|
72
|
+
@namespace = options[:namespace]
|
73
|
+
finalize = options[:finalize] || DEFAULT_FINALIZE
|
74
|
+
instance_exec(&finalize)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Execute `init` step
|
78
|
+
#
|
79
|
+
# @return [Bootable]
|
80
|
+
#
|
81
|
+
# @api public
|
82
|
+
def init
|
83
|
+
trigger(:before, :init)
|
84
|
+
lifecycle.(:init)
|
85
|
+
trigger(:after, :init)
|
86
|
+
self
|
87
|
+
end
|
88
|
+
|
89
|
+
# Execute `start` step
|
90
|
+
#
|
91
|
+
# @return [Bootable]
|
92
|
+
#
|
93
|
+
# @api public
|
94
|
+
def start
|
95
|
+
trigger(:before, :start)
|
96
|
+
lifecycle.(:start)
|
97
|
+
trigger(:after, :start)
|
98
|
+
self
|
99
|
+
end
|
100
|
+
|
101
|
+
# Execute `stop` step
|
102
|
+
#
|
103
|
+
# @return [Bootable]
|
104
|
+
#
|
105
|
+
# @api public
|
106
|
+
def stop
|
107
|
+
lifecycle.(:stop)
|
108
|
+
self
|
109
|
+
end
|
110
|
+
|
111
|
+
# Specify a before callback
|
112
|
+
#
|
113
|
+
# @return [Bootable]
|
114
|
+
#
|
115
|
+
# @api public
|
116
|
+
def before(event, &block)
|
117
|
+
triggers[:before][event] << block
|
118
|
+
self
|
119
|
+
end
|
120
|
+
|
121
|
+
# Specify an after callback
|
122
|
+
#
|
123
|
+
# @return [Bootable]
|
124
|
+
#
|
125
|
+
# @api public
|
126
|
+
def after(event, &block)
|
127
|
+
triggers[:after][event] << block
|
128
|
+
self
|
129
|
+
end
|
130
|
+
|
131
|
+
# Configure a component
|
132
|
+
#
|
133
|
+
# @return [Bootable]
|
134
|
+
#
|
135
|
+
# @api public
|
136
|
+
def configure(&block)
|
137
|
+
@config_block = block
|
138
|
+
end
|
139
|
+
|
140
|
+
# Define configuration settings with keys and types
|
141
|
+
#
|
142
|
+
# @return [Bootable]
|
143
|
+
#
|
144
|
+
# @api public
|
145
|
+
def settings(&block)
|
146
|
+
if block
|
147
|
+
@settings_block = block
|
148
|
+
elsif @settings_block
|
149
|
+
@settings = Settings::DSL.new(identifier, &@settings_block).call
|
150
|
+
else
|
151
|
+
@settings
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
# Return component's configuration
|
156
|
+
#
|
157
|
+
# @return [Dry::Struct]
|
158
|
+
#
|
159
|
+
# @api public
|
160
|
+
def config
|
161
|
+
if @config
|
162
|
+
@config
|
163
|
+
else
|
164
|
+
configure!
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
# Return a list of lifecycle steps that were executed
|
169
|
+
#
|
170
|
+
# @return [Array<Symbol>]
|
171
|
+
#
|
172
|
+
# @api public
|
173
|
+
def statuses
|
174
|
+
lifecycle.statuses
|
175
|
+
end
|
176
|
+
|
177
|
+
# Return system's container used by this component
|
178
|
+
#
|
179
|
+
# @return [Dry::Struct]
|
180
|
+
#
|
181
|
+
# @api public
|
182
|
+
def container
|
183
|
+
options.fetch(:container)
|
184
|
+
end
|
185
|
+
|
186
|
+
# Automatically called by the booter object after starting a component
|
187
|
+
#
|
188
|
+
# @return [Bootable]
|
189
|
+
#
|
190
|
+
# @api private
|
191
|
+
def finalize
|
192
|
+
lifecycle.container.each do |key, item|
|
193
|
+
container.register(key, item) unless container.key?(key)
|
194
|
+
end
|
195
|
+
self
|
196
|
+
end
|
197
|
+
|
198
|
+
# Trigger a callback
|
199
|
+
#
|
200
|
+
# @return [Bootable]
|
201
|
+
#
|
202
|
+
# @api private
|
203
|
+
def trigger(key, event)
|
204
|
+
triggers[key][event].each do |fn|
|
205
|
+
container.instance_exec(lifecycle.container, &fn)
|
206
|
+
end
|
207
|
+
self
|
208
|
+
end
|
209
|
+
|
210
|
+
# Return a new instance with updated options
|
211
|
+
#
|
212
|
+
# @return [Dry::Struct]
|
213
|
+
#
|
214
|
+
# @api private
|
215
|
+
def with(new_options)
|
216
|
+
self.class.new(identifier, options.merge(new_options))
|
217
|
+
end
|
218
|
+
|
219
|
+
# Return true
|
220
|
+
#
|
221
|
+
# @return [TrueClass]
|
222
|
+
#
|
223
|
+
# @api private
|
224
|
+
def boot?
|
225
|
+
true
|
226
|
+
end
|
227
|
+
|
228
|
+
# Return path to component's boot file
|
229
|
+
#
|
230
|
+
# @return [String]
|
231
|
+
#
|
232
|
+
# @api private
|
233
|
+
def boot_file
|
234
|
+
container_boot_files.
|
235
|
+
detect { |path| Pathname(path).basename('.rb').to_s == identifier.to_s }
|
236
|
+
end
|
237
|
+
|
238
|
+
# Return path to boot dir
|
239
|
+
#
|
240
|
+
# @return [String]
|
241
|
+
#
|
242
|
+
# @api private
|
243
|
+
def boot_path
|
244
|
+
container.boot_path
|
245
|
+
end
|
246
|
+
|
247
|
+
# Return all boot files defined under container's boot path
|
248
|
+
#
|
249
|
+
# @return [String]
|
250
|
+
#
|
251
|
+
# @api private
|
252
|
+
def container_boot_files
|
253
|
+
Dir[container.boot_path.join('**/*.rb')]
|
254
|
+
end
|
255
|
+
|
256
|
+
private
|
257
|
+
|
258
|
+
# Return lifecycle object used for this component
|
259
|
+
#
|
260
|
+
# @return [Lifecycle]
|
261
|
+
#
|
262
|
+
# @api private
|
263
|
+
def lifecycle
|
264
|
+
@lifecycle ||= Lifecycle.new(lf_container, component: self, &block)
|
265
|
+
end
|
266
|
+
|
267
|
+
# Return configured container for the lifecycle object
|
268
|
+
#
|
269
|
+
# @return [Dry::Container]
|
270
|
+
#
|
271
|
+
# @api private
|
272
|
+
def lf_container
|
273
|
+
container = Dry::Container.new
|
274
|
+
|
275
|
+
case namespace
|
276
|
+
when String, Symbol
|
277
|
+
container.namespace(namespace) { |c| return c }
|
278
|
+
when true
|
279
|
+
container.namespace(identifier) { |c| return c }
|
280
|
+
when nil
|
281
|
+
container
|
282
|
+
else
|
283
|
+
raise RuntimeError, "+namespace+ boot option must be true, string or symbol #{namespace.inspect} given."
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
# Set config object
|
288
|
+
#
|
289
|
+
# @return [Dry::Struct]
|
290
|
+
#
|
291
|
+
# @api private
|
292
|
+
def configure!
|
293
|
+
@config = settings.new(Config.new(&@config_block)) if settings
|
294
|
+
end
|
295
|
+
|
296
|
+
# Return block that will be evaluated in the lifecycle context
|
297
|
+
#
|
298
|
+
# @return [Proc]
|
299
|
+
#
|
300
|
+
# @api private
|
301
|
+
def block
|
302
|
+
options.fetch(:block)
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end
|
306
|
+
end
|
307
|
+
end
|