dry-system 0.20.0 → 0.21.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 +32 -0
- data/README.md +1 -1
- 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 +70 -38
- 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 +25 -29
- data/lib/dry/system/errors.rb +11 -20
- data/lib/dry/system/identifier.rb +57 -80
- data/lib/dry/system/indirect_component.rb +65 -0
- data/lib/dry/system/loader.rb +2 -3
- data/lib/dry/system/manual_registrar.rb +4 -8
- 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/version.rb +1 -1
- data/lib/dry/system.rb +5 -5
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1c0977524fa33277150e8611a851c557461c14357e1a5d9c1f1929c283f3c9b3
|
4
|
+
data.tar.gz: 12de5eaa25ede9f5f959cd77e2af8f1d3b4b287aaebea1554c2915433743c290
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6976cb749c98ed536c5fb3e6ca67674aee2707b40cd5d196b6b82472edadfa10877bebac77631b0ebcc5fabe008514ed60e7d9be17ccd1343e8967836f319a11
|
7
|
+
data.tar.gz: fd894f982bf214dac3ccfa0de1d4fd7f95beeea1f91234cd2868dfab4687b76ea831c153b429d8ba9bd9f04bcb46dd2815f87a7829e6b347b2d8992cf0ebd478
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,37 @@
|
|
1
1
|
<!--- DO NOT EDIT THIS FILE - IT'S AUTOMATICALLY GENERATED VIA DEVTOOLS --->
|
2
2
|
|
3
|
+
## 0.21.0 2021-11-01
|
4
|
+
|
5
|
+
|
6
|
+
### Added
|
7
|
+
|
8
|
+
- Added **component dir namespaces** as a way to specify multiple, ordered, independent namespace rules within a given component dir. This replaces and expands upon the namespace support we previously provided via the singular `default_namespace` component dir setting (@timriley in #181)
|
9
|
+
|
10
|
+
### Changed
|
11
|
+
|
12
|
+
- `default_namespace` setting on component dirs has been deprecated. Add a component dir namespace instead, e.g. instead of:
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
# Inside Dry::System::Container.configure
|
16
|
+
config.component_dirs.add "lib" do |dir|
|
17
|
+
dir.default_namespace = "admin"
|
18
|
+
end
|
19
|
+
```
|
20
|
+
|
21
|
+
Add this:
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
config.component_dirs.add "lib" do |dir|
|
25
|
+
dir.namespaces.add "admin", key: nil
|
26
|
+
end
|
27
|
+
```
|
28
|
+
|
29
|
+
(@timriley in #181)
|
30
|
+
- `Dry::System::Component#path` has been removed and replaced by `Component#require_path` and `Component#const_path` (@timriley in #181)
|
31
|
+
- Unused `Dry::System::FileNotFoundError` and `Dry::System::InvalidComponentIdentifierTypeError` errors have been removed (@timriley in #194)
|
32
|
+
|
33
|
+
[Compare v0.20.0...v0.21.0](https://github.com/dry-rb/dry-system/compare/v0.20.0...v0.21.0)
|
34
|
+
|
3
35
|
## 0.20.0 2021-09-12
|
4
36
|
|
5
37
|
|
data/README.md
CHANGED
@@ -29,7 +29,7 @@ module Dry
|
|
29
29
|
|
30
30
|
# @api private
|
31
31
|
def call(component_dir)
|
32
|
-
|
32
|
+
component_dir.each_component do |component|
|
33
33
|
next unless register_component?(component)
|
34
34
|
|
35
35
|
container.register(component.key, memoize: component.memoize?) { component.instance }
|
@@ -38,18 +38,6 @@ module Dry
|
|
38
38
|
|
39
39
|
private
|
40
40
|
|
41
|
-
def components(component_dir)
|
42
|
-
files(component_dir.full_path).map { |file_path|
|
43
|
-
component_dir.component_for_path(file_path)
|
44
|
-
}
|
45
|
-
end
|
46
|
-
|
47
|
-
def files(dir)
|
48
|
-
raise ComponentDirNotFoundError, dir unless Dir.exist?(dir)
|
49
|
-
|
50
|
-
Dir["#{dir}/**/#{RB_GLOB}"].sort
|
51
|
-
end
|
52
|
-
|
53
41
|
def register_component?(component)
|
54
42
|
!container.registered?(component.key) && component.auto_register?
|
55
43
|
end
|
@@ -21,13 +21,13 @@ module Dry
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def exists?(name)
|
24
|
-
components.any? { |component| component.
|
24
|
+
components.any? { |component| component.name == name }
|
25
25
|
end
|
26
26
|
|
27
27
|
def [](name)
|
28
|
-
component = components.detect { |
|
28
|
+
component = components.detect { |c| c.name == name }
|
29
29
|
|
30
|
-
component || raise(
|
30
|
+
component || raise(InvalidComponentNameError, name)
|
31
31
|
end
|
32
32
|
end
|
33
33
|
end
|
data/lib/dry/system/booter.rb
CHANGED
@@ -179,15 +179,15 @@ module Dry
|
|
179
179
|
end
|
180
180
|
|
181
181
|
def load_component(path)
|
182
|
-
|
182
|
+
name = Pathname(path).basename(RB_EXT).to_s.to_sym
|
183
183
|
|
184
|
-
Kernel.require path unless components.exists?(
|
184
|
+
Kernel.require path unless components.exists?(name)
|
185
185
|
|
186
186
|
self
|
187
187
|
end
|
188
188
|
|
189
|
-
def require_boot_file(
|
190
|
-
boot_file = find_boot_file(
|
189
|
+
def require_boot_file(name)
|
190
|
+
boot_file = find_boot_file(name)
|
191
191
|
|
192
192
|
Kernel.require boot_file if boot_file
|
193
193
|
end
|
data/lib/dry/system/component.rb
CHANGED
@@ -17,7 +17,7 @@ module Dry
|
|
17
17
|
#
|
18
18
|
# @api public
|
19
19
|
class Component
|
20
|
-
include Dry::Equalizer(:identifier, :
|
20
|
+
include Dry::Equalizer(:identifier, :namespace, :options)
|
21
21
|
|
22
22
|
DEFAULT_OPTIONS = {
|
23
23
|
separator: DEFAULT_SEPARATOR,
|
@@ -26,43 +26,34 @@ module Dry
|
|
26
26
|
}.freeze
|
27
27
|
|
28
28
|
# @!attribute [r] identifier
|
29
|
-
# @return [String] component's unique identifier
|
29
|
+
# @return [String] the component's unique identifier
|
30
30
|
attr_reader :identifier
|
31
31
|
|
32
|
-
# @!attribute [r]
|
33
|
-
# @return [
|
34
|
-
attr_reader :
|
32
|
+
# @!attribute [r] namespace
|
33
|
+
# @return [Dry::System::Config::Namespace] the component's namespace
|
34
|
+
attr_reader :namespace
|
35
35
|
|
36
36
|
# @!attribute [r] options
|
37
|
-
# @return [Hash] component's options
|
37
|
+
# @return [Hash] the component's options
|
38
38
|
attr_reader :options
|
39
39
|
|
40
40
|
# @api private
|
41
|
-
def
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
separator = options.delete(:separator)
|
46
|
-
|
47
|
-
identifier =
|
48
|
-
if identifier.is_a?(Identifier)
|
49
|
-
identifier
|
50
|
-
else
|
51
|
-
Identifier.new(
|
52
|
-
identifier,
|
53
|
-
namespace: namespace,
|
54
|
-
separator: separator
|
55
|
-
)
|
56
|
-
end
|
57
|
-
|
58
|
-
super(identifier, **options)
|
41
|
+
def initialize(identifier, namespace:, **options)
|
42
|
+
@identifier = identifier
|
43
|
+
@namespace = namespace
|
44
|
+
@options = DEFAULT_OPTIONS.merge(options)
|
59
45
|
end
|
60
46
|
|
47
|
+
# Returns true, indicating that the component is directly loadable from the files
|
48
|
+
# managed by the container
|
49
|
+
#
|
50
|
+
# This is the inverse of {IndirectComponent#loadable?}
|
51
|
+
#
|
52
|
+
# @return [TrueClass]
|
53
|
+
#
|
61
54
|
# @api private
|
62
|
-
def
|
63
|
-
|
64
|
-
@file_path = file_path
|
65
|
-
@options = options
|
55
|
+
def loadable?
|
56
|
+
true
|
66
57
|
end
|
67
58
|
|
68
59
|
# Returns the component's instance
|
@@ -74,39 +65,95 @@ module Dry
|
|
74
65
|
end
|
75
66
|
ruby2_keywords(:instance) if respond_to?(:ruby2_keywords, true)
|
76
67
|
|
77
|
-
#
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
68
|
+
# Returns the component's unique key
|
69
|
+
#
|
70
|
+
# @return [String] the key
|
71
|
+
#
|
72
|
+
# @see Identifier#key
|
73
|
+
#
|
74
|
+
# @api public
|
82
75
|
def key
|
83
|
-
identifier.
|
84
|
-
end
|
85
|
-
|
86
|
-
def path
|
87
|
-
identifier.path
|
76
|
+
identifier.key
|
88
77
|
end
|
89
78
|
|
79
|
+
# Returns the root namespace segment of the component's key, as a symbol
|
80
|
+
#
|
81
|
+
# @see Identifier#root_key
|
82
|
+
#
|
83
|
+
# @return [Symbol] the root key
|
84
|
+
#
|
85
|
+
# @api public
|
90
86
|
def root_key
|
91
87
|
identifier.root_key
|
92
88
|
end
|
93
89
|
|
94
|
-
# Returns
|
90
|
+
# Returns a path-delimited representation of the compnent, appropriate for passing
|
91
|
+
# to `Kernel#require` to require its source file
|
95
92
|
#
|
96
|
-
#
|
97
|
-
#
|
98
|
-
|
99
|
-
|
93
|
+
# The path takes into account the rules of the namespace used to load the component.
|
94
|
+
#
|
95
|
+
# @example Component from a root namespace
|
96
|
+
# component.key # => "articles.create"
|
97
|
+
# component.require_path # => "articles/create"
|
98
|
+
#
|
99
|
+
# @example Component from an "admin/" path namespace (with `key: nil`)
|
100
|
+
# component.key # => "articles.create"
|
101
|
+
# component.require_path # => "admin/articles/create"
|
102
|
+
#
|
103
|
+
# @see Config::Namespaces#add
|
104
|
+
# @see Config::Namespace
|
105
|
+
#
|
106
|
+
# @return [String] the require path
|
107
|
+
#
|
108
|
+
# @api public
|
109
|
+
def require_path
|
110
|
+
if namespace.path
|
111
|
+
"#{namespace.path}#{PATH_SEPARATOR}#{path_in_namespace}"
|
112
|
+
else
|
113
|
+
path_in_namespace
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# Returns an "underscored", path-delimited representation of the component,
|
118
|
+
# appropriate for passing to the inflector for constantizing
|
119
|
+
#
|
120
|
+
# The const path takes into account the rules of the namespace used to load the
|
121
|
+
# component.
|
122
|
+
#
|
123
|
+
# @example Component from a namespace with `const: nil`
|
124
|
+
# component.key # => "articles.create_article"
|
125
|
+
# component.const_path # => "articles/create_article"
|
126
|
+
# component.inflector.constantize(component.const_path) # => Articles::CreateArticle
|
127
|
+
#
|
128
|
+
# @example Component from a namespace with `const: "admin"`
|
129
|
+
# component.key # => "articles.create_article"
|
130
|
+
# component.const_path # => "admin/articles/create_article"
|
131
|
+
# component.inflector.constantize(component.const_path) # => Admin::Articles::CreateArticle
|
132
|
+
#
|
133
|
+
# @see Config::Namespaces#add
|
134
|
+
# @see Config::Namespace
|
135
|
+
#
|
136
|
+
# @return [String] the const path
|
137
|
+
#
|
138
|
+
# @api public
|
139
|
+
def const_path
|
140
|
+
namespace_const_path = namespace.const&.gsub(identifier.separator, PATH_SEPARATOR)
|
141
|
+
|
142
|
+
if namespace_const_path
|
143
|
+
"#{namespace_const_path}#{PATH_SEPARATOR}#{path_in_namespace}"
|
144
|
+
else
|
145
|
+
path_in_namespace
|
146
|
+
end
|
100
147
|
end
|
101
148
|
|
102
149
|
# @api private
|
103
150
|
def loader
|
104
|
-
options
|
151
|
+
options.fetch(:loader)
|
105
152
|
end
|
106
153
|
|
107
154
|
# @api private
|
108
155
|
def inflector
|
109
|
-
options
|
156
|
+
options.fetch(:inflector)
|
110
157
|
end
|
111
158
|
|
112
159
|
# @api private
|
@@ -121,6 +168,17 @@ module Dry
|
|
121
168
|
|
122
169
|
private
|
123
170
|
|
171
|
+
def path_in_namespace
|
172
|
+
identifier_in_namespace =
|
173
|
+
if namespace.key
|
174
|
+
identifier.namespaced(from: namespace.key, to: nil)
|
175
|
+
else
|
176
|
+
identifier
|
177
|
+
end
|
178
|
+
|
179
|
+
identifier_in_namespace.key_with_separator(PATH_SEPARATOR)
|
180
|
+
end
|
181
|
+
|
124
182
|
def callable_option?(value)
|
125
183
|
if value.respond_to?(:call)
|
126
184
|
!!value.call(self)
|
@@ -1,4 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "pathname"
|
4
|
+
require "dry/system/constants"
|
2
5
|
require_relative "constants"
|
3
6
|
require_relative "identifier"
|
4
7
|
require_relative "magic_comments_parser"
|
@@ -28,40 +31,101 @@ module Dry
|
|
28
31
|
@container = container
|
29
32
|
end
|
30
33
|
|
31
|
-
# Returns a component for
|
32
|
-
#
|
34
|
+
# Returns a component for the given key if a matching source file is found within
|
35
|
+
# the component dir
|
33
36
|
#
|
34
|
-
# This
|
35
|
-
#
|
37
|
+
# This searches according to the component dir's configured namespaces, in order of
|
38
|
+
# definition, with the first match returned as the component.
|
36
39
|
#
|
37
|
-
# @param
|
40
|
+
# @param key [String] the component's key
|
38
41
|
# @return [Dry::System::Component, nil] the component, if found
|
39
42
|
#
|
40
43
|
# @api private
|
41
|
-
def
|
42
|
-
|
43
|
-
identifier,
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
44
|
+
def component_for_key(key)
|
45
|
+
namespaces.each do |namespace|
|
46
|
+
identifier = Identifier.new(key, separator: container.config.namespace_separator)
|
47
|
+
|
48
|
+
next unless identifier.start_with?(namespace.key)
|
49
|
+
|
50
|
+
if (file_path = find_component_file(identifier, namespace))
|
51
|
+
return build_component(identifier, namespace, file_path)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
nil
|
56
|
+
end
|
57
|
+
|
58
|
+
def each_component
|
59
|
+
return enum_for(:each_component) unless block_given?
|
60
|
+
|
61
|
+
each_file do |file_path, namespace|
|
62
|
+
yield component_for_path(file_path, namespace)
|
50
63
|
end
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def namespaces
|
69
|
+
config.namespaces.to_a.map { |namespace| normalize_namespace(namespace) }
|
70
|
+
end
|
51
71
|
|
52
|
-
|
53
|
-
|
54
|
-
|
72
|
+
# Returns an array of "normalized" namespaces, safe for loading components
|
73
|
+
#
|
74
|
+
# This works around the issue of a namespace being added for a nested path but
|
75
|
+
# _without_ specifying a key namespace. In this case, the key namespace will defaut
|
76
|
+
# to match the path, meaning it will contain path separators instead of the
|
77
|
+
# container's configured `namespace_separator` (due to `Config::Namespaces` not
|
78
|
+
# being able to know the configured `namespace_separator`), so we need to replace
|
79
|
+
# the path separators with the proper `namespace_separator` here (where we _do_ know
|
80
|
+
# what it is).
|
81
|
+
def normalize_namespace(namespace)
|
82
|
+
if namespace.path&.include?(PATH_SEPARATOR) && namespace.default_key?
|
83
|
+
namespace = namespace.class.new(
|
84
|
+
path: namespace.path,
|
85
|
+
key: namespace.key.gsub(PATH_SEPARATOR, container.config.namespace_separator),
|
86
|
+
const: namespace.const
|
87
|
+
)
|
55
88
|
end
|
89
|
+
|
90
|
+
namespace
|
91
|
+
end
|
92
|
+
|
93
|
+
def each_file
|
94
|
+
return enum_for(:each_file) unless block_given?
|
95
|
+
|
96
|
+
raise ComponentDirNotFoundError, full_path unless Dir.exist?(full_path)
|
97
|
+
|
98
|
+
namespaces.each do |namespace|
|
99
|
+
files(namespace).each do |file|
|
100
|
+
yield file, namespace
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def files(namespace)
|
106
|
+
if namespace.path?
|
107
|
+
Dir[File.join(full_path, namespace.path, "**", RB_GLOB)].sort
|
108
|
+
else
|
109
|
+
non_root_paths = namespaces.to_a.reject(&:root?).map(&:path)
|
110
|
+
|
111
|
+
Dir[File.join(full_path, "**", RB_GLOB)].reject { |file_path|
|
112
|
+
Pathname(file_path).relative_path_from(full_path).to_s.start_with?(*non_root_paths)
|
113
|
+
}.sort
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# Returns the full path of the component directory
|
118
|
+
#
|
119
|
+
# @return [Pathname]
|
120
|
+
def full_path
|
121
|
+
container.root.join(path)
|
56
122
|
end
|
57
123
|
|
58
124
|
# Returns a component for a full path to a Ruby source file within the component dir
|
59
125
|
#
|
60
126
|
# @param path [String] the full path to the file
|
61
127
|
# @return [Dry::System::Component] the component
|
62
|
-
|
63
|
-
# @api private
|
64
|
-
def component_for_path(path)
|
128
|
+
def component_for_path(path, namespace)
|
65
129
|
separator = container.config.namespace_separator
|
66
130
|
|
67
131
|
key = Pathname(path).relative_path_from(full_path).to_s
|
@@ -70,46 +134,49 @@ module Dry
|
|
70
134
|
.join(separator)
|
71
135
|
|
72
136
|
identifier = Identifier.new(key, separator: separator)
|
137
|
+
.namespaced(
|
138
|
+
from: namespace.path&.gsub(PATH_SEPARATOR, separator),
|
139
|
+
to: namespace.key
|
140
|
+
)
|
141
|
+
|
142
|
+
build_component(identifier, namespace, path)
|
143
|
+
end
|
73
144
|
|
74
|
-
|
75
|
-
|
145
|
+
def find_component_file(identifier, namespace)
|
146
|
+
# To properly find the file within a namespace with a key, we should strip the key
|
147
|
+
# from beginning of our given identifier
|
148
|
+
if namespace.key
|
149
|
+
identifier = identifier.namespaced(from: namespace.key, to: nil)
|
76
150
|
end
|
77
151
|
|
78
|
-
|
79
|
-
end
|
152
|
+
file_name = "#{identifier.key_with_separator(PATH_SEPARATOR)}#{RB_EXT}"
|
80
153
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
end
|
154
|
+
component_file =
|
155
|
+
if namespace.path?
|
156
|
+
full_path.join(namespace.path, file_name)
|
157
|
+
else
|
158
|
+
full_path.join(file_name)
|
159
|
+
end
|
88
160
|
|
89
|
-
|
90
|
-
def component_options
|
91
|
-
{
|
92
|
-
auto_register: auto_register,
|
93
|
-
loader: loader,
|
94
|
-
memoize: memoize
|
95
|
-
}
|
161
|
+
component_file if component_file.exist?
|
96
162
|
end
|
97
163
|
|
98
|
-
|
99
|
-
|
100
|
-
def build_component(identifier, file_path)
|
164
|
+
def build_component(identifier, namespace, file_path)
|
101
165
|
options = {
|
102
166
|
inflector: container.config.inflector,
|
103
167
|
**component_options,
|
104
168
|
**MagicCommentsParser.(file_path)
|
105
169
|
}
|
106
170
|
|
107
|
-
Component.new(identifier,
|
171
|
+
Component.new(identifier, namespace: namespace, **options)
|
108
172
|
end
|
109
173
|
|
110
|
-
def
|
111
|
-
|
112
|
-
|
174
|
+
def component_options
|
175
|
+
{
|
176
|
+
auto_register: auto_register,
|
177
|
+
loader: loader,
|
178
|
+
memoize: memoize
|
179
|
+
}
|
113
180
|
end
|
114
181
|
|
115
182
|
def method_missing(name, *args, &block)
|
@@ -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
|