dry-system 0.19.0 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +75 -0
- data/README.md +5 -4
- data/dry-system.gemspec +16 -15
- data/lib/dry/system/auto_registrar.rb +3 -15
- data/lib/dry/system/booter/component_registry.rb +3 -3
- data/lib/dry/system/booter.rb +4 -4
- data/lib/dry/system/component.rb +103 -45
- data/lib/dry/system/component_dir.rb +112 -45
- data/lib/dry/system/components/bootable.rb +10 -19
- data/lib/dry/system/config/component_dir.rb +74 -42
- data/lib/dry/system/config/component_dirs.rb +28 -41
- data/lib/dry/system/config/namespace.rb +71 -0
- data/lib/dry/system/config/namespaces.rb +121 -0
- data/lib/dry/system/constants.rb +1 -1
- data/lib/dry/system/container.rb +39 -42
- data/lib/dry/system/errors.rb +11 -20
- data/lib/dry/system/identifier.rb +57 -79
- data/lib/dry/system/indirect_component.rb +65 -0
- data/lib/dry/system/loader.rb +3 -4
- data/lib/dry/system/manual_registrar.rb +4 -8
- data/lib/dry/system/plugins/bootsnap.rb +1 -1
- data/lib/dry/system/plugins/dependency_graph.rb +4 -4
- data/lib/dry/system/plugins/env.rb +1 -1
- data/lib/dry/system/plugins/logging.rb +7 -6
- data/lib/dry/system/plugins.rb +1 -3
- data/lib/dry/system/provider.rb +6 -6
- data/lib/dry/system/provider_registry.rb +4 -4
- data/lib/dry/system/settings.rb +1 -4
- data/lib/dry/system/stubs.rb +1 -1
- data/lib/dry/system/version.rb +1 -1
- data/lib/dry/system.rb +5 -5
- metadata +14 -11
@@ -47,9 +47,9 @@ module Dry
|
|
47
47
|
class Bootable
|
48
48
|
DEFAULT_FINALIZE = proc {}
|
49
49
|
|
50
|
-
# @!attribute [r]
|
51
|
-
# @return [Symbol] component's unique
|
52
|
-
attr_reader :
|
50
|
+
# @!attribute [r] key
|
51
|
+
# @return [Symbol] component's unique name
|
52
|
+
attr_reader :name
|
53
53
|
|
54
54
|
# @!attribute [r] options
|
55
55
|
# @return [Hash] component's options
|
@@ -66,10 +66,10 @@ module Dry
|
|
66
66
|
TRIGGER_MAP = Hash.new { |h, k| h[k] = [] }.freeze
|
67
67
|
|
68
68
|
# @api private
|
69
|
-
def initialize(
|
69
|
+
def initialize(name, options = {}, &block)
|
70
70
|
@config = nil
|
71
71
|
@config_block = nil
|
72
|
-
@
|
72
|
+
@name = name
|
73
73
|
@triggers = {before: TRIGGER_MAP.dup, after: TRIGGER_MAP.dup}
|
74
74
|
@options = block ? options.merge(block: block) : options
|
75
75
|
@namespace = options[:namespace]
|
@@ -149,7 +149,7 @@ module Dry
|
|
149
149
|
if block
|
150
150
|
@settings_block = block
|
151
151
|
elsif @settings_block
|
152
|
-
@settings = Settings::DSL.new(
|
152
|
+
@settings = Settings::DSL.new(&@settings_block).call
|
153
153
|
else
|
154
154
|
@settings
|
155
155
|
end
|
@@ -211,8 +211,8 @@ module Dry
|
|
211
211
|
# @return [Dry::Struct]
|
212
212
|
#
|
213
213
|
# @api private
|
214
|
-
def new(
|
215
|
-
self.class.new(
|
214
|
+
def new(name, new_options = EMPTY_HASH)
|
215
|
+
self.class.new(name, options.merge(new_options))
|
216
216
|
end
|
217
217
|
|
218
218
|
# Return a new instance with updated options
|
@@ -221,16 +221,7 @@ module Dry
|
|
221
221
|
#
|
222
222
|
# @api private
|
223
223
|
def with(new_options)
|
224
|
-
self.class.new(
|
225
|
-
end
|
226
|
-
|
227
|
-
# Return true
|
228
|
-
#
|
229
|
-
# @return [TrueClass]
|
230
|
-
#
|
231
|
-
# @api private
|
232
|
-
def bootable?
|
233
|
-
true
|
224
|
+
self.class.new(name, options.merge(new_options))
|
234
225
|
end
|
235
226
|
|
236
227
|
private
|
@@ -256,7 +247,7 @@ module Dry
|
|
256
247
|
when String, Symbol
|
257
248
|
container.namespace(namespace) { |c| return c }
|
258
249
|
when true
|
259
|
-
container.namespace(
|
250
|
+
container.namespace(name) { |c| return c }
|
260
251
|
when nil
|
261
252
|
container
|
262
253
|
else
|
@@ -1,5 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "dry/configurable"
|
4
|
+
require "dry/core/deprecations"
|
5
|
+
require "dry/system/constants"
|
2
6
|
require "dry/system/loader"
|
7
|
+
require_relative "namespaces"
|
3
8
|
|
4
9
|
module Dry
|
5
10
|
module System
|
@@ -27,7 +32,7 @@ module Dry
|
|
27
32
|
#
|
28
33
|
# @example
|
29
34
|
# dir.auto_register = proc do |component|
|
30
|
-
# !component.start_with?("entities")
|
35
|
+
# !component.identifier.start_with?("entities")
|
31
36
|
# end
|
32
37
|
#
|
33
38
|
# @see auto_register
|
@@ -40,7 +45,7 @@ module Dry
|
|
40
45
|
# @return [Boolean, Proc] the configured policy
|
41
46
|
#
|
42
47
|
# @see auto_register=
|
43
|
-
setting :auto_register, true
|
48
|
+
setting :auto_register, default: true
|
44
49
|
|
45
50
|
# @!method add_to_load_path=(policy)
|
46
51
|
#
|
@@ -63,41 +68,12 @@ module Dry
|
|
63
68
|
# @return [Boolean]
|
64
69
|
#
|
65
70
|
# @see add_to_load_path=
|
66
|
-
setting :add_to_load_path, true
|
67
|
-
|
68
|
-
# @!method default_namespace=(leading_namespace)
|
69
|
-
#
|
70
|
-
# Sets the leading namespace segments to be stripped when registering components
|
71
|
-
# from the dir in the container.
|
72
|
-
#
|
73
|
-
# This is useful to configure when the dir contains components in a module
|
74
|
-
# namespace that you don't want repeated in their identifiers.
|
75
|
-
#
|
76
|
-
# Defaults to `nil`.
|
77
|
-
#
|
78
|
-
# @param leading_namespace [String, nil]
|
79
|
-
# @return [String, nil]
|
80
|
-
#
|
81
|
-
# @example
|
82
|
-
# dir.default_namespace = "my_app"
|
83
|
-
#
|
84
|
-
# @example
|
85
|
-
# dir.default_namespace = "my_app.admin"
|
86
|
-
#
|
87
|
-
# @see default_namespace
|
88
|
-
#
|
89
|
-
# @!method default_namespace
|
90
|
-
#
|
91
|
-
# Returns the configured value.
|
92
|
-
#
|
93
|
-
# @return [String, nil]
|
94
|
-
#
|
95
|
-
# @see default_namespace=
|
96
|
-
setting :default_namespace
|
71
|
+
setting :add_to_load_path, default: true
|
97
72
|
|
98
73
|
# @!method loader=(loader)
|
99
74
|
#
|
100
|
-
# Sets the loader to use when registering
|
75
|
+
# Sets the loader to use when registering components from the dir in the
|
76
|
+
# container.
|
101
77
|
#
|
102
78
|
# Defaults to `Dry::System::Loader`.
|
103
79
|
#
|
@@ -117,7 +93,7 @@ module Dry
|
|
117
93
|
# @return [#call]
|
118
94
|
#
|
119
95
|
# @see loader=
|
120
|
-
setting :loader, Dry::System::Loader
|
96
|
+
setting :loader, default: Dry::System::Loader
|
121
97
|
|
122
98
|
# @!method memoize=(policy)
|
123
99
|
#
|
@@ -138,7 +114,7 @@ module Dry
|
|
138
114
|
#
|
139
115
|
# @example
|
140
116
|
# dir.memoize = proc do |component|
|
141
|
-
# !component.start_with?("providers")
|
117
|
+
# !component.identifier.start_with?("providers")
|
142
118
|
# end
|
143
119
|
#
|
144
120
|
# @see memoize
|
@@ -151,7 +127,50 @@ module Dry
|
|
151
127
|
# @return [Boolean, Proc] the configured memoization policy
|
152
128
|
#
|
153
129
|
# @see memoize=
|
154
|
-
setting :memoize, false
|
130
|
+
setting :memoize, default: false
|
131
|
+
|
132
|
+
# @!method namespaces
|
133
|
+
#
|
134
|
+
# Returns the configured namespaces for the component dir.
|
135
|
+
#
|
136
|
+
# Allows namespaces to added on the returned object via {Namespaces#add}.
|
137
|
+
#
|
138
|
+
# @see Namespaces#add
|
139
|
+
#
|
140
|
+
# @return [Namespaces] the namespaces
|
141
|
+
setting :namespaces, default: Namespaces.new, cloneable: true
|
142
|
+
|
143
|
+
def default_namespace=(namespace)
|
144
|
+
Dry::Core::Deprecations.announce(
|
145
|
+
"Dry::System::Config::ComponentDir#default_namespace=",
|
146
|
+
"Add a namespace instead: `dir.namespaces.add #{namespace.to_s.inspect}, key: nil`",
|
147
|
+
tag: "dry-system",
|
148
|
+
uplevel: 1
|
149
|
+
)
|
150
|
+
|
151
|
+
# We don't have the configured separator here, so the best we can do is guess
|
152
|
+
# that it's a dot
|
153
|
+
namespace_path = namespace.gsub(".", PATH_SEPARATOR)
|
154
|
+
|
155
|
+
return if namespaces.namespaces[namespace_path]
|
156
|
+
|
157
|
+
namespaces.add namespace_path, key: nil
|
158
|
+
end
|
159
|
+
|
160
|
+
def default_namespace
|
161
|
+
Dry::Core::Deprecations.announce(
|
162
|
+
"Dry::System::Config::ComponentDir#default_namespace",
|
163
|
+
"Use namespaces instead, e.g. `dir.namespaces`",
|
164
|
+
tag: "dry-system",
|
165
|
+
uplevel: 1
|
166
|
+
)
|
167
|
+
|
168
|
+
ns_path = namespaces.to_a.reject(&:root?).first&.path
|
169
|
+
|
170
|
+
# We don't have the configured separator here, so the best we can do is guess
|
171
|
+
# that it's a dot
|
172
|
+
ns_path&.gsub(PATH_SEPARATOR, ".")
|
173
|
+
end
|
155
174
|
|
156
175
|
# @!endgroup
|
157
176
|
|
@@ -172,15 +191,28 @@ module Dry
|
|
172
191
|
!!config.auto_register
|
173
192
|
end
|
174
193
|
|
175
|
-
# Returns true if
|
176
|
-
# just a default value.
|
194
|
+
# Returns true if the given setting has been explicitly configured by the user
|
177
195
|
#
|
178
|
-
# This is used
|
179
|
-
#
|
196
|
+
# This is used when determining whether to apply system-wide default values to a
|
197
|
+
# component dir (explicitly configured settings will not be overridden by
|
198
|
+
# defaults)
|
180
199
|
#
|
200
|
+
# @param key [Symbol] the setting name
|
201
|
+
#
|
202
|
+
# @return [Boolean]
|
203
|
+
#
|
204
|
+
# @see Dry::System::Config::ComponentDirs#apply_defaults_to_dir
|
181
205
|
# @api private
|
182
206
|
def configured?(key)
|
183
|
-
|
207
|
+
case key
|
208
|
+
when :namespaces
|
209
|
+
# Because we mutate the default value for the `namespaces` setting, rather
|
210
|
+
# than assign a new one, to check if it's configured we must see whether any
|
211
|
+
# namespaces have been added
|
212
|
+
!config.namespaces.empty?
|
213
|
+
else
|
214
|
+
config._settings[key].input_defined?
|
215
|
+
end
|
184
216
|
end
|
185
217
|
|
186
218
|
private
|
@@ -1,5 +1,6 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "concurrent/map"
|
2
|
-
require "dry/configurable"
|
3
4
|
require "dry/system/constants"
|
4
5
|
require "dry/system/errors"
|
5
6
|
require_relative "component_dir"
|
@@ -8,13 +9,6 @@ module Dry
|
|
8
9
|
module System
|
9
10
|
module Config
|
10
11
|
class ComponentDirs
|
11
|
-
include Dry::Configurable
|
12
|
-
|
13
|
-
# Settings from ComponentDir are configured here as defaults for all added dirs
|
14
|
-
ComponentDir._settings.each do |setting|
|
15
|
-
_settings << setting.dup
|
16
|
-
end
|
17
|
-
|
18
12
|
# @!group Settings
|
19
13
|
|
20
14
|
# @!method auto_register=(value)
|
@@ -43,19 +37,6 @@ module Dry
|
|
43
37
|
#
|
44
38
|
# @see add_to_load_path=
|
45
39
|
|
46
|
-
# @!method default_namespace=(value)
|
47
|
-
#
|
48
|
-
# Sets a default `default_namespace` value for all added component dirs
|
49
|
-
#
|
50
|
-
# @see ComponentDir.default_namespace
|
51
|
-
# @see default_namespace
|
52
|
-
#
|
53
|
-
# @!method default_namespace
|
54
|
-
#
|
55
|
-
# Returns the configured default `default_namespace`
|
56
|
-
#
|
57
|
-
# @see default_namespace=
|
58
|
-
|
59
40
|
# @!method loader=(value)
|
60
41
|
#
|
61
42
|
# Sets a default `loader` value for all added component dirs
|
@@ -82,17 +63,34 @@ module Dry
|
|
82
63
|
#
|
83
64
|
# @see memoize=
|
84
65
|
|
66
|
+
# @!method namespaces
|
67
|
+
#
|
68
|
+
# Returns the default configured namespaces for all added component dirs
|
69
|
+
#
|
70
|
+
# Allows namespaces to added on the returned object via {Namespaces#add}.
|
71
|
+
#
|
72
|
+
# @see Namespaces#add
|
73
|
+
#
|
74
|
+
# @return [Namespaces] the namespaces
|
75
|
+
|
85
76
|
# @!endgroup
|
86
77
|
|
78
|
+
# A ComponentDir for configuring the default values to apply to all added
|
79
|
+
# component dirs
|
80
|
+
#
|
81
|
+
# @api private
|
82
|
+
attr_reader :defaults
|
83
|
+
|
87
84
|
# @api private
|
88
85
|
def initialize
|
89
86
|
@dirs = Concurrent::Map.new
|
87
|
+
@defaults = ComponentDir.new(nil)
|
90
88
|
end
|
91
89
|
|
92
90
|
# @api private
|
93
91
|
def initialize_copy(source)
|
94
|
-
super
|
95
92
|
@dirs = source.dirs.dup
|
93
|
+
@defaults = source.defaults.dup
|
96
94
|
end
|
97
95
|
|
98
96
|
# Adds and configures a component dir
|
@@ -114,8 +112,8 @@ module Dry
|
|
114
112
|
raise ComponentDirAlreadyAddedError, path if dirs.key?(path)
|
115
113
|
|
116
114
|
dirs[path] = ComponentDir.new(path).tap do |dir|
|
117
|
-
apply_defaults_to_dir(dir)
|
118
115
|
yield dir if block_given?
|
116
|
+
apply_defaults_to_dir(dir)
|
119
117
|
end
|
120
118
|
end
|
121
119
|
|
@@ -143,40 +141,29 @@ module Dry
|
|
143
141
|
|
144
142
|
private
|
145
143
|
|
146
|
-
#
|
144
|
+
# Applies default settings to a component dir. This is run every time the dirs are
|
147
145
|
# accessed to ensure defaults are applied regardless of when new component dirs
|
148
146
|
# are added. This method must be idempotent.
|
149
147
|
#
|
150
148
|
# @return [void]
|
151
149
|
def apply_defaults_to_dir(dir)
|
152
|
-
|
153
|
-
if configured?(key) && !dir.configured?(key)
|
154
|
-
dir.public_send(:"#{key}=", public_send(key))
|
150
|
+
defaults.config.values.each do |key, _|
|
151
|
+
if defaults.configured?(key) && !dir.configured?(key)
|
152
|
+
dir.public_send(:"#{key}=", defaults.public_send(key).dup)
|
155
153
|
end
|
156
154
|
end
|
157
155
|
end
|
158
156
|
|
159
|
-
# Returns true if a setting has been explicitly configured and is not returning
|
160
|
-
# just a default value.
|
161
|
-
#
|
162
|
-
# This is used to determine which settings should be applied to added component
|
163
|
-
# dirs as additional defaults.
|
164
|
-
#
|
165
|
-
# @api private
|
166
|
-
def configured?(key)
|
167
|
-
config._settings[key].input_defined?
|
168
|
-
end
|
169
|
-
|
170
157
|
def method_missing(name, *args, &block)
|
171
|
-
if
|
172
|
-
|
158
|
+
if defaults.respond_to?(name)
|
159
|
+
defaults.public_send(name, *args, &block)
|
173
160
|
else
|
174
161
|
super
|
175
162
|
end
|
176
163
|
end
|
177
164
|
|
178
165
|
def respond_to_missing?(name, include_all = false)
|
179
|
-
|
166
|
+
defaults.respond_to?(name) || super
|
180
167
|
end
|
181
168
|
end
|
182
169
|
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/core/equalizer"
|
4
|
+
|
5
|
+
module Dry
|
6
|
+
module System
|
7
|
+
module Config
|
8
|
+
# A configured namespace for a component dir
|
9
|
+
#
|
10
|
+
# Namespaces consist of three elements:
|
11
|
+
#
|
12
|
+
# - The `path` within the component dir to which its namespace rules should apply.
|
13
|
+
# - A `key`, which determines the leading part of the key used to register
|
14
|
+
# each component in the container.
|
15
|
+
# - A `const`, which is the Ruby namespace expected to contain the class constants
|
16
|
+
# defined within each component's source file. This value is expected to be an
|
17
|
+
# "underscored" string, intended to be run through the configured inflector to be
|
18
|
+
# converted into a real constant (e.g. `"foo_bar/baz"` will become `FooBar::Baz`)
|
19
|
+
#
|
20
|
+
# Namespaces are added and configured for a component dir via {Namespaces#add}.
|
21
|
+
#
|
22
|
+
# @see Namespaces#add
|
23
|
+
#
|
24
|
+
# @api private
|
25
|
+
class Namespace
|
26
|
+
ROOT_PATH = nil
|
27
|
+
|
28
|
+
include Dry::Equalizer(:path, :key, :const)
|
29
|
+
|
30
|
+
attr_reader :path
|
31
|
+
|
32
|
+
attr_reader :key
|
33
|
+
|
34
|
+
attr_reader :const
|
35
|
+
|
36
|
+
# Returns a namespace configured to serve as the default root namespace for a
|
37
|
+
# component dir, ensuring that all code within the dir can be loaded, regardless
|
38
|
+
# of any other explictly configured namespaces
|
39
|
+
#
|
40
|
+
# @return [Namespace] the root namespace
|
41
|
+
#
|
42
|
+
# @api private
|
43
|
+
def self.default_root
|
44
|
+
new(
|
45
|
+
path: ROOT_PATH,
|
46
|
+
key: nil,
|
47
|
+
const: nil
|
48
|
+
)
|
49
|
+
end
|
50
|
+
|
51
|
+
def initialize(path:, key:, const:)
|
52
|
+
@path = path
|
53
|
+
@key = key
|
54
|
+
@const = const
|
55
|
+
end
|
56
|
+
|
57
|
+
def root?
|
58
|
+
path == ROOT_PATH
|
59
|
+
end
|
60
|
+
|
61
|
+
def path?
|
62
|
+
!root?
|
63
|
+
end
|
64
|
+
|
65
|
+
def default_key?
|
66
|
+
key == path
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/system/errors"
|
4
|
+
require_relative "namespace"
|
5
|
+
|
6
|
+
module Dry
|
7
|
+
module System
|
8
|
+
module Config
|
9
|
+
# The configured namespaces for a ComponentDir
|
10
|
+
#
|
11
|
+
# @see Config::ComponentDir#namespaces
|
12
|
+
#
|
13
|
+
# @api private
|
14
|
+
class Namespaces
|
15
|
+
# @api private
|
16
|
+
attr_reader :namespaces
|
17
|
+
|
18
|
+
# @api private
|
19
|
+
def initialize
|
20
|
+
@namespaces = {}
|
21
|
+
end
|
22
|
+
|
23
|
+
# @api private
|
24
|
+
def initialize_copy(source)
|
25
|
+
super
|
26
|
+
@namespaces = source.namespaces.dup
|
27
|
+
end
|
28
|
+
|
29
|
+
# rubocop:disable Layout/LineLength
|
30
|
+
|
31
|
+
# Adds a component dir namespace
|
32
|
+
#
|
33
|
+
# A namespace encompasses a given sub-directory of the component dir, and
|
34
|
+
# determines (1) the leading segments of its components' registered identifiers,
|
35
|
+
# and (2) the expected constant namespace of their class constants.
|
36
|
+
#
|
37
|
+
# A namespace for a path can only be added once.
|
38
|
+
#
|
39
|
+
# @example Adding a namespace with top-level identifiers
|
40
|
+
# # Components defined within admin/ (e.g. admin/my_component.rb) will be:
|
41
|
+
# #
|
42
|
+
# # - Registered with top-level identifiers ("my_component")
|
43
|
+
# # - Expected to have constants in `Admin`, matching the namespace's path (Admin::MyComponent)
|
44
|
+
#
|
45
|
+
# namespaces.add "admin", key: nil
|
46
|
+
#
|
47
|
+
# @example Adding a namespace with top-level class constants
|
48
|
+
# # Components defined within adapters/ (e.g. adapters/my_adapter.rb) will be:
|
49
|
+
# #
|
50
|
+
# # - Registered with leading identifiers matching the namespace's path ("adapters.my_adapter")
|
51
|
+
# # - Expected to have top-level constants (::MyAdapter)
|
52
|
+
#
|
53
|
+
# namespaces.add "adapters", const: nil
|
54
|
+
#
|
55
|
+
# @example Adding a namespace with distinct identifiers and class constants
|
56
|
+
# # Components defined within `bananas/` (e.g. bananas/banana_split.rb) will be:
|
57
|
+
# #
|
58
|
+
# # - Registered with the given leading identifier ("desserts.banana_split")
|
59
|
+
# # - Expected to have constants within the given namespace (EatMe::Now::BananaSplit)
|
60
|
+
#
|
61
|
+
# namespaces.add "bananas", key: "desserts", const: "eat_me/now"
|
62
|
+
#
|
63
|
+
# @param path [String] the path to the sub-directory of source files to which this
|
64
|
+
# namespace should apply, relative to the component dir
|
65
|
+
# @param identifier [String, nil] the leading namespace to apply to the registered
|
66
|
+
# identifiers for the components. Set `nil` for the identifiers to be top-level.
|
67
|
+
# @param const [String, nil] the Ruby constant namespace to expect for constants
|
68
|
+
# defined within the components. This should be provided in underscored string
|
69
|
+
# form, e.g. "hello_there/world" for a Ruby constant of `HelloThere::World`. Set
|
70
|
+
# `nil` for the constants to be top-level.
|
71
|
+
#
|
72
|
+
# @return [Namespace] the added namespace
|
73
|
+
#
|
74
|
+
# @see Namespace
|
75
|
+
#
|
76
|
+
# @api public
|
77
|
+
def add(path, key: path, const: path)
|
78
|
+
raise NamespaceAlreadyAddedError, path if namespaces.key?(path)
|
79
|
+
|
80
|
+
namespaces[path] = Namespace.new(path: path, key: key, const: const)
|
81
|
+
end
|
82
|
+
|
83
|
+
# rubocop:enable Layout/LineLength
|
84
|
+
|
85
|
+
# Adds a root component dir namespace
|
86
|
+
#
|
87
|
+
# @see #add
|
88
|
+
#
|
89
|
+
# @api public
|
90
|
+
def root(key: nil, const: nil)
|
91
|
+
add(Namespace::ROOT_PATH, key: key, const: const)
|
92
|
+
end
|
93
|
+
|
94
|
+
# @api private
|
95
|
+
def empty?
|
96
|
+
namespaces.empty?
|
97
|
+
end
|
98
|
+
|
99
|
+
# Returns the configured namespaces as an array
|
100
|
+
#
|
101
|
+
# This adds a root namespace to the end of the array if one was not configured
|
102
|
+
# manually. This fallback ensures that all components in the component dir can be
|
103
|
+
# loaded.
|
104
|
+
#
|
105
|
+
# @return [Array<Namespace>] the namespaces
|
106
|
+
#
|
107
|
+
# @api private
|
108
|
+
def to_a
|
109
|
+
namespaces.values.tap do |arr|
|
110
|
+
arr << Namespace.default_root unless arr.any?(&:root?)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# @api private
|
115
|
+
def each(&block)
|
116
|
+
to_a.each(&block)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|