dry-system 0.19.2 → 0.23.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 +472 -1
- data/LICENSE +1 -1
- data/README.md +4 -3
- data/dry-system.gemspec +16 -15
- data/lib/dry/system/auto_registrar.rb +1 -13
- data/lib/dry/system/component.rb +104 -47
- data/lib/dry/system/component_dir.rb +88 -47
- data/lib/dry/system/components.rb +8 -4
- data/lib/dry/system/config/component_dir.rb +141 -53
- data/lib/dry/system/config/component_dirs.rb +176 -70
- data/lib/dry/system/config/namespace.rb +76 -0
- data/lib/dry/system/config/namespaces.rb +208 -0
- data/lib/dry/system/constants.rb +2 -2
- data/lib/dry/system/container.rb +279 -201
- data/lib/dry/system/errors.rb +72 -61
- data/lib/dry/system/identifier.rb +99 -79
- data/lib/dry/system/importer.rb +83 -12
- data/lib/dry/system/indirect_component.rb +65 -0
- data/lib/dry/system/loader.rb +8 -4
- data/lib/dry/system/{manual_registrar.rb → manifest_registrar.rb} +12 -13
- data/lib/dry/system/plugins/bootsnap.rb +3 -2
- data/lib/dry/system/plugins/dependency_graph/strategies.rb +37 -1
- data/lib/dry/system/plugins/dependency_graph.rb +26 -20
- data/lib/dry/system/plugins/env.rb +3 -2
- data/lib/dry/system/plugins/logging.rb +9 -5
- data/lib/dry/system/plugins/monitoring.rb +1 -1
- data/lib/dry/system/plugins/notifications.rb +1 -1
- data/lib/dry/system/plugins/zeitwerk/compat_inflector.rb +22 -0
- data/lib/dry/system/plugins/zeitwerk.rb +109 -0
- data/lib/dry/system/plugins.rb +8 -7
- data/lib/dry/system/provider/source.rb +324 -0
- data/lib/dry/system/provider/source_dsl.rb +94 -0
- data/lib/dry/system/provider.rb +264 -24
- data/lib/dry/system/provider_registrar.rb +276 -0
- data/lib/dry/system/provider_source_registry.rb +70 -0
- data/lib/dry/system/provider_sources/settings/config.rb +86 -0
- data/lib/dry/system/provider_sources/settings/loader.rb +53 -0
- data/lib/dry/system/provider_sources/settings.rb +40 -0
- data/lib/dry/system/provider_sources.rb +5 -0
- data/lib/dry/system/stubs.rb +1 -1
- data/lib/dry/system/version.rb +1 -1
- data/lib/dry/system.rb +45 -13
- metadata +25 -22
- data/lib/dry/system/booter/component_registry.rb +0 -35
- data/lib/dry/system/booter.rb +0 -200
- data/lib/dry/system/components/bootable.rb +0 -289
- data/lib/dry/system/components/config.rb +0 -35
- data/lib/dry/system/lifecycle.rb +0 -135
- data/lib/dry/system/provider_registry.rb +0 -27
- data/lib/dry/system/settings/file_loader.rb +0 -30
- data/lib/dry/system/settings/file_parser.rb +0 -51
- data/lib/dry/system/settings.rb +0 -67
- data/lib/dry/system/system_components/settings.rb +0 -11
@@ -1,9 +1,15 @@
|
|
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
|
6
11
|
module Config
|
12
|
+
# @api public
|
7
13
|
class ComponentDir
|
8
14
|
include Dry::Configurable
|
9
15
|
|
@@ -14,7 +20,7 @@ module Dry
|
|
14
20
|
# Sets the auto-registration policy for the component dir.
|
15
21
|
#
|
16
22
|
# This may be a simple boolean to enable or disable auto-registration for all
|
17
|
-
# components, or a proc accepting a
|
23
|
+
# components, or a proc accepting a {Dry::System::Component} and returning a
|
18
24
|
# boolean to configure auto-registration on a per-component basis
|
19
25
|
#
|
20
26
|
# Defaults to `true`.
|
@@ -27,11 +33,12 @@ module Dry
|
|
27
33
|
#
|
28
34
|
# @example
|
29
35
|
# dir.auto_register = proc do |component|
|
30
|
-
# !component.start_with?("entities")
|
36
|
+
# !component.identifier.start_with?("entities")
|
31
37
|
# end
|
32
38
|
#
|
33
39
|
# @see auto_register
|
34
40
|
# @see Component
|
41
|
+
# @api public
|
35
42
|
#
|
36
43
|
# @!method auto_register
|
37
44
|
#
|
@@ -40,68 +47,61 @@ module Dry
|
|
40
47
|
# @return [Boolean, Proc] the configured policy
|
41
48
|
#
|
42
49
|
# @see auto_register=
|
43
|
-
|
50
|
+
# @api public
|
51
|
+
setting :auto_register, default: true
|
44
52
|
|
45
|
-
# @!method
|
46
|
-
#
|
47
|
-
# Sets whether the dir should be added to the `$LOAD_PATH` after the container
|
48
|
-
# is configured.
|
49
|
-
#
|
50
|
-
# Defaults to `true`. This may need to be set to `false` when using a class
|
51
|
-
# autoloading system.
|
53
|
+
# @!method instance=(instance_proc)
|
52
54
|
#
|
53
|
-
#
|
54
|
-
#
|
55
|
+
# Sets a proc used to return the instance of any component within the component
|
56
|
+
# dir.
|
55
57
|
#
|
56
|
-
#
|
57
|
-
#
|
58
|
+
# This proc should accept a {Dry::System::Component} and return the object to
|
59
|
+
# serve as the component's instance.
|
58
60
|
#
|
59
|
-
#
|
60
|
-
#
|
61
|
-
#
|
62
|
-
#
|
63
|
-
#
|
64
|
-
#
|
65
|
-
# @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.
|
61
|
+
# When you provide an instance proc, it will be used in preference to the
|
62
|
+
# {loader} (either the default loader or an explicitly configured one). Provide
|
63
|
+
# an instance proc when you want a simple way to customize the instance for
|
64
|
+
# certain components. For complete control, provide a replacement loader via
|
65
|
+
# {loader=}.
|
75
66
|
#
|
76
67
|
# Defaults to `nil`.
|
77
68
|
#
|
78
|
-
# @param
|
79
|
-
# @return [
|
69
|
+
# @param instance_proc [Proc, nil]
|
70
|
+
# @return [Proc]
|
80
71
|
#
|
81
72
|
# @example
|
82
|
-
# dir.
|
83
|
-
#
|
84
|
-
#
|
85
|
-
#
|
73
|
+
# dir.instance = proc do |component|
|
74
|
+
# if component.key.match?(/workers\./)
|
75
|
+
# # Register classes for jobs
|
76
|
+
# component.loader.constant(component)
|
77
|
+
# else
|
78
|
+
# # Otherwise register regular instances per default loader
|
79
|
+
# component.loader.call(component)
|
80
|
+
# end
|
81
|
+
# end
|
86
82
|
#
|
87
|
-
# @see
|
83
|
+
# @see Component, Loader
|
84
|
+
# @api public
|
88
85
|
#
|
89
|
-
# @!method
|
86
|
+
# @!method instance
|
90
87
|
#
|
91
|
-
# Returns the configured
|
88
|
+
# Returns the configured instance proc.
|
92
89
|
#
|
93
|
-
# @return [
|
90
|
+
# @return [Proc, nil]
|
94
91
|
#
|
95
|
-
# @see
|
96
|
-
|
92
|
+
# @see instance=
|
93
|
+
# @api public
|
94
|
+
setting :instance
|
97
95
|
|
98
96
|
# @!method loader=(loader)
|
99
97
|
#
|
100
|
-
# Sets the loader to use when registering
|
98
|
+
# Sets the loader to use when registering components from the dir in the
|
99
|
+
# container.
|
101
100
|
#
|
102
101
|
# Defaults to `Dry::System::Loader`.
|
103
102
|
#
|
104
|
-
# When using
|
103
|
+
# When using an autoloader like Zeitwerk, consider using
|
104
|
+
# `Dry::System::Loader::Autoloading`
|
105
105
|
#
|
106
106
|
# @param loader [#call] the loader
|
107
107
|
# @return [#call] the configured loader
|
@@ -109,6 +109,7 @@ module Dry
|
|
109
109
|
# @see loader
|
110
110
|
# @see Loader
|
111
111
|
# @see Loader::Autoloading
|
112
|
+
# @api public
|
112
113
|
#
|
113
114
|
# @!method loader
|
114
115
|
#
|
@@ -117,7 +118,8 @@ module Dry
|
|
117
118
|
# @return [#call]
|
118
119
|
#
|
119
120
|
# @see loader=
|
120
|
-
|
121
|
+
# @api public
|
122
|
+
setting :loader, default: Dry::System::Loader
|
121
123
|
|
122
124
|
# @!method memoize=(policy)
|
123
125
|
#
|
@@ -138,11 +140,12 @@ module Dry
|
|
138
140
|
#
|
139
141
|
# @example
|
140
142
|
# dir.memoize = proc do |component|
|
141
|
-
# !component.start_with?("providers")
|
143
|
+
# !component.identifier.start_with?("providers")
|
142
144
|
# end
|
143
145
|
#
|
144
146
|
# @see memoize
|
145
147
|
# @see Component
|
148
|
+
# @api public
|
146
149
|
#
|
147
150
|
# @!method memoize
|
148
151
|
#
|
@@ -151,7 +154,79 @@ module Dry
|
|
151
154
|
# @return [Boolean, Proc] the configured memoization policy
|
152
155
|
#
|
153
156
|
# @see memoize=
|
154
|
-
|
157
|
+
# @api public
|
158
|
+
setting :memoize, default: false
|
159
|
+
|
160
|
+
# @!method namespaces
|
161
|
+
#
|
162
|
+
# Returns the configured namespaces for the component dir.
|
163
|
+
#
|
164
|
+
# Allows namespaces to added on the returned object via {Namespaces#add}.
|
165
|
+
#
|
166
|
+
# @return [Namespaces] the namespaces
|
167
|
+
#
|
168
|
+
# @see Namespaces#add
|
169
|
+
# @api public
|
170
|
+
setting :namespaces, default: Namespaces.new, cloneable: true
|
171
|
+
|
172
|
+
# @!method add_to_load_path=(policy)
|
173
|
+
#
|
174
|
+
# Sets whether the dir should be added to the `$LOAD_PATH` after the container
|
175
|
+
# is configured.
|
176
|
+
#
|
177
|
+
# Defaults to `true`. This may need to be set to `false` when using a class
|
178
|
+
# autoloading system.
|
179
|
+
#
|
180
|
+
# @param policy [Boolean]
|
181
|
+
# @return [Boolean]
|
182
|
+
#
|
183
|
+
# @see add_to_load_path
|
184
|
+
# @see Container.configure
|
185
|
+
# @api public
|
186
|
+
#
|
187
|
+
# @!method add_to_load_path
|
188
|
+
#
|
189
|
+
# Returns the configured value.
|
190
|
+
#
|
191
|
+
# @return [Boolean]
|
192
|
+
#
|
193
|
+
# @see add_to_load_path=
|
194
|
+
# @api public
|
195
|
+
setting :add_to_load_path, default: true
|
196
|
+
|
197
|
+
# @api public
|
198
|
+
def default_namespace=(namespace)
|
199
|
+
Dry::Core::Deprecations.announce(
|
200
|
+
"Dry::System::Config::ComponentDir#default_namespace=",
|
201
|
+
"Add a namespace instead: `dir.namespaces.add #{namespace.to_s.inspect}, key: nil`",
|
202
|
+
tag: "dry-system",
|
203
|
+
uplevel: 1
|
204
|
+
)
|
205
|
+
|
206
|
+
# We don't have the configured separator here, so the best we can do is guess
|
207
|
+
# that it's a dot
|
208
|
+
namespace_path = namespace.gsub(".", PATH_SEPARATOR)
|
209
|
+
|
210
|
+
return if namespaces.namespaces[namespace_path]
|
211
|
+
|
212
|
+
namespaces.add namespace_path, key: nil
|
213
|
+
end
|
214
|
+
|
215
|
+
# @api public
|
216
|
+
def default_namespace
|
217
|
+
Dry::Core::Deprecations.announce(
|
218
|
+
"Dry::System::Config::ComponentDir#default_namespace",
|
219
|
+
"Use namespaces instead, e.g. `dir.namespaces`",
|
220
|
+
tag: "dry-system",
|
221
|
+
uplevel: 1
|
222
|
+
)
|
223
|
+
|
224
|
+
ns_path = namespaces.to_a.reject(&:root?).first&.path
|
225
|
+
|
226
|
+
# We don't have the configured separator here, so the best we can do is guess
|
227
|
+
# that it's a dot
|
228
|
+
ns_path&.gsub(PATH_SEPARATOR, ".")
|
229
|
+
end
|
155
230
|
|
156
231
|
# @!endgroup
|
157
232
|
|
@@ -160,7 +235,7 @@ module Dry
|
|
160
235
|
# @return [String] the path
|
161
236
|
attr_reader :path
|
162
237
|
|
163
|
-
# @api
|
238
|
+
# @api public
|
164
239
|
def initialize(path)
|
165
240
|
super()
|
166
241
|
@path = path
|
@@ -172,15 +247,28 @@ module Dry
|
|
172
247
|
!!config.auto_register
|
173
248
|
end
|
174
249
|
|
175
|
-
# Returns true if
|
176
|
-
# just a default value.
|
250
|
+
# Returns true if the given setting has been explicitly configured by the user
|
177
251
|
#
|
178
|
-
# This is used
|
179
|
-
#
|
252
|
+
# This is used when determining whether to apply system-wide default values to a
|
253
|
+
# component dir (explicitly configured settings will not be overridden by
|
254
|
+
# defaults)
|
180
255
|
#
|
256
|
+
# @param key [Symbol] the setting name
|
257
|
+
#
|
258
|
+
# @return [Boolean]
|
259
|
+
#
|
260
|
+
# @see Dry::System::Config::ComponentDirs#apply_defaults_to_dir
|
181
261
|
# @api private
|
182
262
|
def configured?(key)
|
183
|
-
|
263
|
+
case key
|
264
|
+
when :namespaces
|
265
|
+
# Because we mutate the default value for the `namespaces` setting, rather
|
266
|
+
# than assign a new one, to check if it's configured we must see whether any
|
267
|
+
# namespaces have been added
|
268
|
+
!config.namespaces.empty?
|
269
|
+
else
|
270
|
+
config._settings[key].input_defined?
|
271
|
+
end
|
184
272
|
end
|
185
273
|
|
186
274
|
private
|
@@ -1,5 +1,5 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
3
|
require "dry/system/constants"
|
4
4
|
require "dry/system/errors"
|
5
5
|
require_relative "component_dir"
|
@@ -7,21 +7,17 @@ require_relative "component_dir"
|
|
7
7
|
module Dry
|
8
8
|
module System
|
9
9
|
module Config
|
10
|
+
# The configured component dirs for a container
|
11
|
+
#
|
12
|
+
# @api public
|
10
13
|
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
14
|
# @!group Settings
|
19
15
|
|
20
16
|
# @!method auto_register=(value)
|
21
17
|
#
|
22
18
|
# Sets a default `auto_register` for all added component dirs
|
23
19
|
#
|
24
|
-
# @see ComponentDir.auto_register
|
20
|
+
# @see ComponentDir.auto_register=
|
25
21
|
# @see auto_register
|
26
22
|
#
|
27
23
|
# @!method auto_register
|
@@ -30,37 +26,24 @@ module Dry
|
|
30
26
|
#
|
31
27
|
# @see auto_register=
|
32
28
|
|
33
|
-
# @!method
|
34
|
-
#
|
35
|
-
# Sets a default `add_to_load_path` value for all added component dirs
|
36
|
-
#
|
37
|
-
# @see ComponentDir.add_to_load_path
|
38
|
-
# @see add_to_load_path
|
39
|
-
#
|
40
|
-
# @!method add_to_load_path
|
41
|
-
#
|
42
|
-
# Returns the configured default `add_to_load_path`
|
43
|
-
#
|
44
|
-
# @see add_to_load_path=
|
45
|
-
|
46
|
-
# @!method default_namespace=(value)
|
29
|
+
# @!method instance=(value)
|
47
30
|
#
|
48
|
-
# Sets a default `
|
31
|
+
# Sets a default `instance` for all added component dirs
|
49
32
|
#
|
50
|
-
# @see ComponentDir.
|
51
|
-
# @see
|
33
|
+
# @see ComponentDir.instance=
|
34
|
+
# @see auto_register
|
52
35
|
#
|
53
|
-
# @!method
|
36
|
+
# @!method auto_register
|
54
37
|
#
|
55
|
-
# Returns the configured default `
|
38
|
+
# Returns the configured default `instance`
|
56
39
|
#
|
57
|
-
# @see
|
40
|
+
# @see instance=
|
58
41
|
|
59
42
|
# @!method loader=(value)
|
60
43
|
#
|
61
44
|
# Sets a default `loader` value for all added component dirs
|
62
45
|
#
|
63
|
-
# @see ComponentDir.loader
|
46
|
+
# @see ComponentDir.loader=
|
64
47
|
# @see loader
|
65
48
|
#
|
66
49
|
# @!method loader
|
@@ -73,7 +56,7 @@ module Dry
|
|
73
56
|
#
|
74
57
|
# Sets a default `memoize` value for all added component dirs
|
75
58
|
#
|
76
|
-
# @see ComponentDir.memoize
|
59
|
+
# @see ComponentDir.memoize=
|
77
60
|
# @see memoize
|
78
61
|
#
|
79
62
|
# @!method memoize
|
@@ -82,54 +65,154 @@ module Dry
|
|
82
65
|
#
|
83
66
|
# @see memoize=
|
84
67
|
|
68
|
+
# rubocop:disable Layout/LineLength
|
69
|
+
|
70
|
+
# @!method namespaces
|
71
|
+
#
|
72
|
+
# Returns the default configured namespaces for all added component dirs
|
73
|
+
#
|
74
|
+
# Allows namespaces to added on the returned object via {Dry::System::Config::Namespaces#add}.
|
75
|
+
#
|
76
|
+
# @see Dry::System::Config::Namespaces#add
|
77
|
+
#
|
78
|
+
# @return [Namespaces] the namespaces
|
79
|
+
|
80
|
+
# @!method add_to_load_path=(value)
|
81
|
+
#
|
82
|
+
# Sets a default `add_to_load_path` value for all added component dirs
|
83
|
+
#
|
84
|
+
# @see ComponentDir.add_to_load_path=
|
85
|
+
# @see add_to_load_path
|
86
|
+
#
|
87
|
+
# @!method add_to_load_path
|
88
|
+
#
|
89
|
+
# Returns the configured default `add_to_load_path`
|
90
|
+
#
|
91
|
+
# @see add_to_load_path=
|
92
|
+
|
93
|
+
# rubocop:enable Layout/LineLength
|
94
|
+
|
85
95
|
# @!endgroup
|
86
96
|
|
97
|
+
# A ComponentDir for configuring the default values to apply to all added
|
98
|
+
# component dirs
|
99
|
+
#
|
100
|
+
# @see #method_missing
|
101
|
+
# @api private
|
102
|
+
attr_reader :defaults
|
103
|
+
|
104
|
+
# Creates a new component dirs
|
105
|
+
#
|
87
106
|
# @api private
|
88
107
|
def initialize
|
89
|
-
@dirs =
|
108
|
+
@dirs = {}
|
109
|
+
@defaults = ComponentDir.new(nil)
|
90
110
|
end
|
91
111
|
|
92
112
|
# @api private
|
93
113
|
def initialize_copy(source)
|
94
|
-
|
95
|
-
@
|
114
|
+
@dirs = source.dirs.map { |path, dir| [path, dir.dup] }.to_h
|
115
|
+
@defaults = source.defaults.dup
|
116
|
+
end
|
117
|
+
|
118
|
+
# Returns and optionally yields a previously added component dir
|
119
|
+
#
|
120
|
+
# @param path [String] the path for the component dir
|
121
|
+
# @yieldparam dir [ComponentDir] the component dir
|
122
|
+
#
|
123
|
+
# @return [ComponentDir] the component dir
|
124
|
+
#
|
125
|
+
# @api public
|
126
|
+
def dir(path)
|
127
|
+
dirs[path].tap do |dir|
|
128
|
+
# Defaults can be (re-)applied first, since the dir has already been added
|
129
|
+
apply_defaults_to_dir(dir) if dir
|
130
|
+
yield dir if block_given?
|
131
|
+
end
|
96
132
|
end
|
133
|
+
alias_method :[], :dir
|
97
134
|
|
98
|
-
#
|
135
|
+
# @overload add(path)
|
136
|
+
# Adds and configures a component dir for the given path
|
137
|
+
#
|
138
|
+
# @param path [String] the path for the component dir, relative to the configured
|
139
|
+
# container root
|
140
|
+
# @yieldparam dir [ComponentDir] the component dir to configure
|
99
141
|
#
|
100
|
-
#
|
101
|
-
# container root
|
142
|
+
# @return [ComponentDir] the added component dir
|
102
143
|
#
|
103
|
-
#
|
144
|
+
# @example
|
145
|
+
# component_dirs.add "lib" do |dir|
|
146
|
+
# dir.default_namespace = "my_app"
|
147
|
+
# end
|
104
148
|
#
|
105
|
-
#
|
149
|
+
# @see ComponentDir
|
150
|
+
# @api public
|
106
151
|
#
|
107
|
-
# @
|
108
|
-
#
|
109
|
-
# dir.default_namespace = "my_app"
|
110
|
-
# end
|
152
|
+
# @overload add(dir)
|
153
|
+
# Adds a configured component dir
|
111
154
|
#
|
112
|
-
#
|
113
|
-
|
155
|
+
# @param dir [ComponentDir] the configured component dir
|
156
|
+
#
|
157
|
+
# @return [ComponentDir] the added component dir
|
158
|
+
#
|
159
|
+
# @example
|
160
|
+
# dir = Dry::System::ComponentDir.new("lib")
|
161
|
+
# component_dirs.add dir
|
162
|
+
#
|
163
|
+
# @see ComponentDir
|
164
|
+
# @api public
|
165
|
+
def add(path_or_dir)
|
166
|
+
path, dir_to_add = path_and_dir(path_or_dir)
|
167
|
+
|
114
168
|
raise ComponentDirAlreadyAddedError, path if dirs.key?(path)
|
115
169
|
|
116
|
-
dirs[path] =
|
170
|
+
dirs[path] = dir_to_add.tap do |dir|
|
171
|
+
# Defaults must be applied after yielding, since the dir is being newly added,
|
172
|
+
# and must have its configuration fully in place before we can know which
|
173
|
+
# defaults to apply
|
174
|
+
yield dir if path_or_dir == path && block_given?
|
117
175
|
apply_defaults_to_dir(dir)
|
118
|
-
yield dir if block_given?
|
119
176
|
end
|
120
177
|
end
|
121
178
|
|
122
|
-
#
|
179
|
+
# Deletes and returns a previously added component dir
|
180
|
+
#
|
181
|
+
# @param path [String] the path for the component dir
|
182
|
+
#
|
183
|
+
# @return [ComponentDir] the removed component dir
|
184
|
+
#
|
185
|
+
# @api public
|
186
|
+
def delete(path)
|
187
|
+
dirs.delete(path)
|
188
|
+
end
|
189
|
+
|
190
|
+
# Returns the paths of the component dirs
|
191
|
+
#
|
192
|
+
# @return [Array<String>] the component dir paths
|
193
|
+
#
|
194
|
+
# @api public
|
195
|
+
def paths
|
196
|
+
dirs.keys
|
197
|
+
end
|
198
|
+
|
199
|
+
# Returns the count of component dirs
|
200
|
+
#
|
201
|
+
# @return [Integer]
|
123
202
|
#
|
124
|
-
# @
|
125
|
-
def
|
126
|
-
|
203
|
+
# @api public
|
204
|
+
def length
|
205
|
+
dirs.length
|
127
206
|
end
|
207
|
+
alias_method :size, :length
|
128
208
|
|
129
209
|
# Returns the added component dirs, with default settings applied
|
130
210
|
#
|
131
211
|
# @return [Array<ComponentDir>]
|
212
|
+
#
|
213
|
+
# @api public
|
132
214
|
def to_a
|
215
|
+
dirs.each { |_, dir| apply_defaults_to_dir(dir) }
|
133
216
|
dirs.values
|
134
217
|
end
|
135
218
|
|
@@ -137,46 +220,69 @@ module Dry
|
|
137
220
|
# argument.
|
138
221
|
#
|
139
222
|
# @yieldparam dir [ComponentDir] the yielded component dir
|
223
|
+
#
|
224
|
+
# @api public
|
140
225
|
def each(&block)
|
141
226
|
to_a.each(&block)
|
142
227
|
end
|
143
228
|
|
229
|
+
protected
|
230
|
+
|
231
|
+
# Returns the hash of component dirs, keyed by their paths
|
232
|
+
#
|
233
|
+
# Recently changed default configuration may not be applied to these dirs. Use
|
234
|
+
# #to_a or #each to access dirs with default configuration fully applied.
|
235
|
+
#
|
236
|
+
# This method exists to encapsulate the instance variable and to serve the needs
|
237
|
+
# of #initialize_copy
|
238
|
+
#
|
239
|
+
# @return [Hash{String => ComponentDir}]
|
240
|
+
#
|
241
|
+
# @api private
|
242
|
+
attr_reader :dirs
|
243
|
+
|
144
244
|
private
|
145
245
|
|
146
|
-
#
|
246
|
+
# Converts a path string or pre-built component dir into a path and dir tuple
|
247
|
+
#
|
248
|
+
# @param path_or_dir [String,ComponentDir]
|
249
|
+
#
|
250
|
+
# @return [Array<(String, ComponentDir)>]
|
251
|
+
#
|
252
|
+
# @see #add
|
253
|
+
def path_and_dir(path_or_dir)
|
254
|
+
if path_or_dir.is_a?(ComponentDir)
|
255
|
+
dir = path_or_dir
|
256
|
+
[dir.path, dir]
|
257
|
+
else
|
258
|
+
path = path_or_dir
|
259
|
+
[path, ComponentDir.new(path)]
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
# Applies default settings to a component dir. This is run every time the dirs are
|
147
264
|
# accessed to ensure defaults are applied regardless of when new component dirs
|
148
265
|
# are added. This method must be idempotent.
|
149
266
|
#
|
150
267
|
# @return [void]
|
151
268
|
def apply_defaults_to_dir(dir)
|
152
|
-
|
153
|
-
if configured?(key) && !dir.configured?(key)
|
154
|
-
dir.public_send(:"#{key}=", public_send(key))
|
269
|
+
defaults.config.values.each do |key, _|
|
270
|
+
if defaults.configured?(key) && !dir.configured?(key)
|
271
|
+
dir.public_send(:"#{key}=", defaults.public_send(key).dup)
|
155
272
|
end
|
156
273
|
end
|
157
274
|
end
|
158
275
|
|
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
276
|
def method_missing(name, *args, &block)
|
171
|
-
if
|
172
|
-
|
277
|
+
if defaults.respond_to?(name)
|
278
|
+
defaults.public_send(name, *args, &block)
|
173
279
|
else
|
174
280
|
super
|
175
281
|
end
|
176
282
|
end
|
177
283
|
|
178
284
|
def respond_to_missing?(name, include_all = false)
|
179
|
-
|
285
|
+
defaults.respond_to?(name) || super
|
180
286
|
end
|
181
287
|
end
|
182
288
|
end
|