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