nxt_registry 0.3.4 → 0.3.10

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b3c4dec7379f1076565a8fa2306e9aba2bfbd12f1191648929635db61a7b4a94
4
- data.tar.gz: '081a471bb51c5e53089ee8341f439b8b70bdb22bb45c24add42673210ecacd0c'
3
+ metadata.gz: 3263cdc8c48171dfc6ecfe2bbe2eedb97d72e0ab8d367945ed04ec2480b2caa0
4
+ data.tar.gz: a7f48fa6c75182d1489cdcb28f19127892bd63b3de655e3e0db40e1b81204031
5
5
  SHA512:
6
- metadata.gz: 7913f84e7bfea3f58efd487eb9bbdc34c988fb3297101aa52525e530c8a6bec5b2d5bc6dfc81bd188f4145c99a74dbbb65b556b6acf847b16df529a65b612999
7
- data.tar.gz: 59fe97c3fe3bbc653bd63f6e7bd835d08189136fc328d9ce0fa62e8199dcc311fa152d2d0ebedb1b7a580b3ef20a6253dfbb02c605a700f88a42076bd57935be
6
+ metadata.gz: 672c5855be89793548452a157d5c196b7a79271269ff43d056b18a2711b2c6ce7fb7cccca11892e05161fcf682eed15b55d7194bc27968d0d99b1066ae8b5ecc
7
+ data.tar.gz: ae6e5c77734afc4d9f732e7179fa62ef1f4b96c5a1278632cb91ce79ea33b803bd22b83f4084711d674698b786f6749033349ed541b152c05b43532936d53df3
data/CHANGELOG.md CHANGED
@@ -1,3 +1,20 @@
1
+ # v0.3.10 2021-03-30
2
+ - Do not synchronize resolve with mutex
3
+
4
+ # v0.3.9 2021-03-10
5
+
6
+ - Synchronize access with Mutex
7
+ - Add key_resolver
8
+ - Fix: Inherit options set through accessors
9
+
10
+ # v0.3.5 2020-12-23
11
+
12
+ - Allow to inherit options in nested registries
13
+
14
+ # v0.3.5 2020-12-04
15
+
16
+ - Allow patterns as keys
17
+
1
18
  # v0.3.4 2020-12-04
2
19
 
3
20
  - Bring back Singleton
data/Gemfile.lock CHANGED
@@ -1,26 +1,26 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- nxt_registry (0.3.4)
4
+ nxt_registry (0.3.10)
5
5
  activesupport
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- activesupport (6.0.3.4)
10
+ activesupport (6.1.3.2)
11
11
  concurrent-ruby (~> 1.0, >= 1.0.2)
12
- i18n (>= 0.7, < 2)
13
- minitest (~> 5.1)
14
- tzinfo (~> 1.1)
15
- zeitwerk (~> 2.2, >= 2.2.2)
12
+ i18n (>= 1.6, < 2)
13
+ minitest (>= 5.1)
14
+ tzinfo (~> 2.0)
15
+ zeitwerk (~> 2.3)
16
16
  coderay (1.1.3)
17
- concurrent-ruby (1.1.7)
17
+ concurrent-ruby (1.1.8)
18
18
  diff-lcs (1.4.4)
19
- i18n (1.8.5)
19
+ i18n (1.8.10)
20
20
  concurrent-ruby (~> 1.0)
21
21
  method_source (1.0.0)
22
- minitest (5.14.2)
23
- pry (0.13.1)
22
+ minitest (5.14.4)
23
+ pry (0.14.1)
24
24
  coderay (~> 1.1)
25
25
  method_source (~> 1.0)
26
26
  rake (12.3.3)
@@ -28,24 +28,24 @@ GEM
28
28
  rspec-core (~> 3.10.0)
29
29
  rspec-expectations (~> 3.10.0)
30
30
  rspec-mocks (~> 3.10.0)
31
- rspec-core (3.10.0)
31
+ rspec-core (3.10.1)
32
32
  rspec-support (~> 3.10.0)
33
- rspec-expectations (3.10.0)
33
+ rspec-expectations (3.10.1)
34
34
  diff-lcs (>= 1.2.0, < 2.0)
35
35
  rspec-support (~> 3.10.0)
36
- rspec-mocks (3.10.0)
36
+ rspec-mocks (3.10.1)
37
37
  diff-lcs (>= 1.2.0, < 2.0)
38
38
  rspec-support (~> 3.10.0)
39
- rspec-support (3.10.0)
39
+ rspec-support (3.10.1)
40
40
  rspec_junit_formatter (0.4.1)
41
41
  rspec-core (>= 2, < 4, != 2.12.0)
42
- thread_safe (0.3.6)
43
- tzinfo (1.2.8)
44
- thread_safe (~> 0.1)
42
+ tzinfo (2.0.4)
43
+ concurrent-ruby (~> 1.0)
45
44
  zeitwerk (2.4.2)
46
45
 
47
46
  PLATFORMS
48
47
  ruby
48
+ x86_64-darwin-19
49
49
 
50
50
  DEPENDENCIES
51
51
  bundler (~> 2.0)
@@ -56,4 +56,4 @@ DEPENDENCIES
56
56
  rspec_junit_formatter
57
57
 
58
58
  BUNDLED WITH
59
- 2.1.4
59
+ 2.2.4
data/README.md CHANGED
@@ -2,8 +2,7 @@
2
2
 
3
3
  # NxtRegistry
4
4
 
5
- `NxtRegistry` is a simple implementation of the container pattern. It allows you to register and resolve values in nested
6
- structures.
5
+ `NxtRegistry` is a simple container that allows you to register and resolve values in nested structures.
7
6
 
8
7
  ## Installation
9
8
 
@@ -82,6 +81,30 @@ OtherExample.registry(:errors).resolve(KeyError)
82
81
  OtherExample.registry(:country_codes).resolve(:germany)
83
82
  # => :de
84
83
  ```
84
+
85
+ ## Register Patterns
86
+
87
+ You can also register values with patterns as keys. Non pattern keys are always evaluated first and then patterns
88
+ will be tried to match by definition sequence.
89
+
90
+ ```ruby
91
+ class Example
92
+ extend NxtRegistry
93
+
94
+ registry :status_codes do
95
+ register(/\A4\d{2}\z/, 'Client errors')
96
+ register(/\A5.*\z/, 'Server errors')
97
+ register('422', 'Unprocessable Entity')
98
+ register(:'503', 'Internal Server Error')
99
+ end
100
+ end
101
+
102
+ Example.registry(:status_codes).resolve('503') # => "Internal Server Error"
103
+ Example.registry(:status_codes).resolve(503) # => "Internal Server Error"
104
+ Example.registry(:status_codes).resolve(422) # => "Unprocessable Entity"
105
+ Example.registry(:status_codes).resolve(404) # => "Client Errors"
106
+ ```
107
+
85
108
  ### Readers
86
109
 
87
110
  Access your defined registries with the `registry(:country_code)` method.
@@ -111,6 +134,23 @@ Nested.registry(:developers).resolve(:frontend, :igor)
111
134
  # => 'Igor'
112
135
  ```
113
136
 
137
+ #### Inherit options in nested registries
138
+
139
+ ```ruby
140
+ class Nested
141
+ extend NxtRegistry
142
+
143
+ registry :developers, default: 'options can be inherited' do
144
+ register(:frontend, inherit_options: true) do
145
+ register(:igor, 'Igor')
146
+ register(:ben, 'Ben')
147
+ end
148
+ end
149
+ end
150
+
151
+ Nested.registry(:developers).resolve(:frontend, :blank)
152
+ # => 'options can be inherited'
153
+ ```
114
154
 
115
155
  ### Defining specific nesting levels of a registry
116
156
 
@@ -164,12 +204,21 @@ Layer.registry(:path).from(:munich).to(:amsterdam).via(:train) # => 'train'
164
204
 
165
205
  *Note that this feature is also available for registries with a single level only.*
166
206
 
167
- ### Restrict attributes to a certain set
207
+ ### Restrict keys to a certain set
168
208
 
169
- Use `attrs` to restrict which attributes can be registered on a specific level.
209
+ Use `allowed_keys` to restrict which keys can be registered on a specific level.
170
210
 
171
211
  ```ruby
172
- registry :example, attrs: %w[one two three]
212
+ registry :example, allowed_keys: %w[one two three]
213
+ ```
214
+
215
+ ### Require a certain set of keys to be registered
216
+
217
+ Use `required_keys` to enforce a certain set of keys to be registered on a specific level. This is especially helpful
218
+ if you use registries in multiple places and you want to ensure they all register the same set of keys.
219
+
220
+ ```ruby
221
+ registry :example, required_keys: %w[one two three]
173
222
  ```
174
223
 
175
224
  ### Default values
@@ -208,19 +257,21 @@ registry.resolve(:one)
208
257
  # => 2020-01-02 23:56:18 +0100
209
258
  ```
210
259
 
211
- ### Resolver
260
+ ### Resolve callbacks
212
261
 
213
- You can register a resolver block if you want to lay hands on your values after they have been resolved.
214
- A resolver can be anything that implements `:call` to which the value is passed.
262
+ You can hook into the before and after resolver callbacks in case you need to lay hands on your values
263
+ before and / or after resolving. A callback can be anything that implements `:call` to which the value is passed.
215
264
 
216
265
  ```ruby
217
266
  registry :example do
218
- resolver ->(value) { value * 2 }
219
- register(:one, 1)
267
+ key_resolver ->(key) { key.strip }
268
+ resolver ->(value) { value.upcase }
269
+
270
+ register(:input, 'output')
220
271
  end
221
272
 
222
- registry.resolve(:one)
223
- # => 2
273
+ registry.resolve(' input ')
274
+ # => 'OUTPUT'
224
275
  ```
225
276
 
226
277
  ### Transform keys
data/lib/nxt_registry.rb CHANGED
@@ -1,7 +1,7 @@
1
+ require 'active_support'
1
2
  require 'active_support/core_ext'
2
3
  require 'nxt_registry/version'
3
4
  require 'nxt_registry/blank'
4
- require 'nxt_registry/attribute'
5
5
  require 'nxt_registry/errors'
6
6
  require 'nxt_registry/registry_builder'
7
7
  require 'nxt_registry/registry'
@@ -2,5 +2,7 @@ module NxtRegistry
2
2
  module Errors
3
3
  KeyAlreadyRegisteredError = Class.new(KeyError)
4
4
  KeyNotRegisteredError = Class.new(KeyError)
5
+ RequiredKeyMissing = Class.new(KeyError)
6
+ KeyNotAllowed = Class.new(KeyError)
5
7
  end
6
8
  end
@@ -8,14 +8,15 @@ module NxtRegistry
8
8
  @namespace = build_namespace
9
9
  @config = config
10
10
  @store = {}
11
- @attrs = nil
12
11
  @configured = false
12
+ @patterns = []
13
+ @config = config
14
+ @mutex = Mutex.new
13
15
 
14
- setup_defaults(options)
15
16
  configure(&config)
16
17
  end
17
18
 
18
- attr_reader :name
19
+ attr_reader :name, :mutex
19
20
  attr_accessor :configured
20
21
 
21
22
  def level(name, **options, &config)
@@ -38,27 +39,33 @@ module NxtRegistry
38
39
  end
39
40
 
40
41
  def registry(name, **options, &config)
41
- opts = options.merge(parent: self)
42
+ opts = conditionally_inherit_options(options)
42
43
  register(name, Registry.new(name, **opts, &config))
43
44
  end
44
45
 
45
46
  def registry!(name, **options, &config)
46
- opts = options.merge(parent: self)
47
+ opts = conditionally_inherit_options(options)
47
48
  register!(name, Registry.new(name, **opts, &config))
48
49
  end
49
50
 
50
- def attr(name)
51
- key = transformed_key(name)
52
- raise KeyError, "Attribute #{key} already registered in #{namespace}" if attrs[key]
51
+ def required_keys(*keys)
52
+ @required_keys ||= []
53
+ return @required_keys if keys.empty?
54
+
55
+ @required_keys += keys.map { |key| transformed_key(key) }
56
+ end
57
+
58
+ def allowed_keys(*keys)
59
+ @allowed_keys ||= []
60
+ return @allowed_keys if keys.empty?
53
61
 
54
- attrs[key] = Attribute.new(key, self)
62
+ @allowed_keys += keys.map { |key| transformed_key(key) }
55
63
  end
56
64
 
57
- def attrs(*args)
58
- @attrs ||= {}
59
- return @attrs unless args.any?
65
+ alias attrs allowed_keys # @deprecated
60
66
 
61
- args.each { |name| attr(name) }
67
+ def attr(key)
68
+ allowed_keys(key) # @deprecated
62
69
  end
63
70
 
64
71
  def register(key = Blank.new, value = Blank.new, **options, &block)
@@ -126,15 +133,18 @@ module NxtRegistry
126
133
  end
127
134
 
128
135
  def fetch(key, *args, &block)
129
- store.fetch(transformed_key(key), *args, &block)
136
+ key = matching_key(key)
137
+ store.fetch(key, *args, &block)
130
138
  end
131
139
 
132
140
  delegate :size, :values, :each, :freeze, to: :store
133
141
 
134
142
  def configure(&block)
143
+ setup_defaults(options)
135
144
  define_accessors
136
145
  define_interface
137
- attrs(*Array(options.fetch(:attrs, [])))
146
+ allowed_keys(*Array(options.fetch(:allowed_keys, [])))
147
+ required_keys(*Array(options.fetch(:required_keys, [])))
138
148
 
139
149
  if block.present?
140
150
  if block.arity == 1
@@ -144,6 +154,7 @@ module NxtRegistry
144
154
  end
145
155
  end
146
156
 
157
+ validate_required_keys_given
147
158
  self.configured = true
148
159
  end
149
160
 
@@ -151,34 +162,59 @@ module NxtRegistry
151
162
  "Registry[#{name}] -> #{store.to_s}"
152
163
  end
153
164
 
154
- alias_method :inspect, :to_s
165
+ alias inspect to_s
155
166
 
156
167
  private
157
168
 
158
- attr_reader :namespace, :parent, :config, :store, :options, :accessor
169
+ attr_reader :namespace, :parent, :config, :store, :options, :accessor, :patterns
159
170
  attr_accessor :is_leaf, :interface_defined
160
171
 
172
+ def conditionally_inherit_options(opts)
173
+ base = opts.delete(:inherit_options) ? options : {}
174
+ base.merge(opts).merge(parent: self)
175
+ end
176
+
177
+ def validate_required_keys_given
178
+ required_keys.each do |key|
179
+ next if store.key?(key)
180
+
181
+ raise Errors::RequiredKeyMissing, "Required key '#{key}' missing in #{self}"
182
+ end
183
+ end
184
+
161
185
  def is_leaf?
162
186
  @is_leaf
163
187
  end
164
188
 
165
189
  def __register(key, value, raise_on_key_already_registered: true)
166
- key = transformed_key(key)
190
+ mutex.synchronize do
191
+ key = if key.is_a?(Regexp)
192
+ patterns << key
193
+ key
194
+ else
195
+ transformed_key(key)
196
+ end
167
197
 
168
- raise ArgumentError, "Not allowed to register values in a registry that contains nested registries" unless is_leaf
169
- raise KeyError, "Keys are restricted to #{attrs.keys}" if attribute_not_allowed?(key)
198
+ raise ArgumentError, "Not allowed to register values in a registry that contains nested registries" unless is_leaf
199
+ raise KeyError, "Keys are restricted to #{allowed_keys}" if key_not_allowed?(key)
170
200
 
171
- on_key_already_registered && on_key_already_registered.call(key) if store[key] && raise_on_key_already_registered
201
+ on_key_already_registered && on_key_already_registered.call(key) if store[key] && raise_on_key_already_registered
172
202
 
173
- store[key] = value
203
+ store[key] = value
204
+ end
174
205
  end
175
206
 
176
207
  def __resolve(key, raise_on_key_not_registered: true)
208
+
177
209
  key = transformed_key(key)
178
210
 
179
211
  value = if is_leaf?
180
- if store.key?(key)
181
- store.fetch(key)
212
+ resolved_key = key_resolver.call(key)
213
+
214
+ if store.key?(resolved_key)
215
+ store.fetch(resolved_key)
216
+ elsif (pattern = matching_pattern(resolved_key))
217
+ store.fetch(pattern)
182
218
  else
183
219
  if is_a_blank?(default)
184
220
  return unless raise_on_key_not_registered
@@ -195,27 +231,40 @@ module NxtRegistry
195
231
  store[key] ||= default.call
196
232
  end
197
233
 
198
- value = if value.respond_to?(:call) && call && !value.is_a?(NxtRegistry::Registry)
199
- value.call(*[key].take(value.arity))
200
- else
201
- value
202
- end
234
+ value = call_or_value(value, key)
203
235
 
204
- if resolver
205
- resolver.call(value)
206
- else
207
- value
208
- end
236
+ resolver.call(value)
237
+ end
238
+
239
+ def matching_key(key)
240
+ key = transformed_key(key)
241
+ # if key is present it always wins over patterns
242
+ return key if store.key?(key)
243
+
244
+ matching_pattern(key) || key
245
+ end
246
+
247
+ def call_or_value(value, key)
248
+ return value unless call
249
+ return value if value.is_a?(NxtRegistry::Registry)
250
+ return value unless value.respond_to?(:call)
251
+
252
+ args = [key, value]
253
+ value.call(*args.take(value.arity))
254
+ end
255
+
256
+ def matching_pattern(key)
257
+ patterns.find { |pattern| key.match?(pattern) }
209
258
  end
210
259
 
211
260
  def define_interface
212
261
  return if interface_defined
213
262
 
214
- raise_invalid_accessor_name(accessor) if respond_to?(accessor)
263
+ raise_invalid_accessor_name(accessor) if respond_to?(accessor.to_s)
215
264
  accessor_with_bang = "#{accessor}!"
216
265
  raise_invalid_accessor_name(accessor_with_bang) if respond_to?(accessor_with_bang)
217
266
 
218
- define_singleton_method accessor do |key = Blank.new, value = Blank.new|
267
+ define_singleton_method accessor.to_s do |key = Blank.new, value = Blank.new|
219
268
  return self if is_a_blank?(key)
220
269
 
221
270
  key = transformed_key(key)
@@ -246,8 +295,9 @@ module NxtRegistry
246
295
  @default = options.fetch(:default) { Blank.new }
247
296
  @memoize = options.fetch(:memoize) { true }
248
297
  @call = options.fetch(:call) { true }
249
- @resolver = options.fetch(:resolver, false)
250
- @transform_keys = options.fetch(:transform_keys) { ->(key) { key.to_s } }
298
+ @resolver = options.fetch(:resolver, ->(val) { val })
299
+ @key_resolver = options.fetch(:key_resolver, ->(val) { val })
300
+ @transform_keys = options.fetch(:transform_keys) { ->(key) { key.is_a?(Regexp) ? key : key.to_s } }
251
301
  @accessor = options.fetch(:accessor) { name }
252
302
 
253
303
  @on_key_already_registered = options.fetch(:on_key_already_registered) { ->(key) { raise_key_already_registered_error(key) } }
@@ -255,27 +305,29 @@ module NxtRegistry
255
305
  end
256
306
 
257
307
  def define_accessors
258
- %w[default memoize call resolver transform_keys on_key_already_registered on_key_not_registered].each do |attribute|
308
+ %w[default memoize call resolver key_resolver transform_keys on_key_already_registered on_key_not_registered].each do |attribute|
259
309
  define_singleton_method attribute do |value = Blank.new, &block|
260
310
  value = block if block
261
311
 
262
312
  if is_a_blank?(value)
263
313
  instance_variable_get("@#{attribute}")
264
314
  else
315
+ options[attribute.to_sym] ||= value
265
316
  instance_variable_set("@#{attribute}", value)
266
317
  end
267
318
  end
268
319
 
269
320
  define_singleton_method "#{attribute}=" do |value|
321
+ options[attribute.to_sym] ||= value
270
322
  instance_variable_set("@#{attribute}", value)
271
323
  end
272
324
  end
273
325
  end
274
326
 
275
- def attribute_not_allowed?(key)
276
- return if attrs.empty?
327
+ def key_not_allowed?(key)
328
+ return if allowed_keys.empty?
277
329
 
278
- attrs.keys.exclude?(transformed_key(key))
330
+ allowed_keys.exclude?(transformed_key(key))
279
331
  end
280
332
 
281
333
  def resolve_default(key)
@@ -305,12 +357,6 @@ module NxtRegistry
305
357
  end
306
358
  end
307
359
 
308
- def initialize_copy(original)
309
- super
310
- @store = original.send(:store).deep_dup
311
- @options = original.send(:options).deep_dup
312
- end
313
-
314
360
  def build_namespace
315
361
  parent ? name.to_s.prepend("#{parent.send(:namespace)}.") : name.to_s
316
362
  end
@@ -326,5 +372,16 @@ module NxtRegistry
326
372
  def raise_invalid_accessor_name(name)
327
373
  raise ArgumentError, "#{self} already implements a method named: #{name}. Please choose a different accessor name"
328
374
  end
375
+
376
+ def initialize_copy(original)
377
+ super
378
+
379
+ @mutex = Mutex.new
380
+ containers = %i[store options]
381
+ variables = %i[patterns required_keys allowed_keys namespace on_key_already_registered on_key_not_registered]
382
+
383
+ containers.each { |c| instance_variable_set("@#{c}", original.send(c).deep_dup) }
384
+ variables.each { |v| instance_variable_set("@#{v}", original.send(v).dup) }
385
+ end
329
386
  end
330
387
  end
@@ -1,3 +1,3 @@
1
1
  module NxtRegistry
2
- VERSION = "0.3.4"
2
+ VERSION = '0.3.10'
3
3
  end
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nxt_registry
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.4
4
+ version: 0.3.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andreas Robecke
8
8
  - Nils Sommer
9
9
  - Raphael Kallensee
10
10
  - Lütfi Demirci
11
- autorequire:
11
+ autorequire:
12
12
  bindir: exe
13
13
  cert_chain: []
14
- date: 2020-12-04 00:00:00.000000000 Z
14
+ date: 2021-06-10 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: activesupport
@@ -83,7 +83,7 @@ dependencies:
83
83
  - - ">="
84
84
  - !ruby/object:Gem::Version
85
85
  version: '0'
86
- description:
86
+ description:
87
87
  email:
88
88
  - a.robecke@hellogetsafe.com
89
89
  - andreas@robecke.de
@@ -106,7 +106,6 @@ files:
106
106
  - bin/console
107
107
  - bin/setup
108
108
  - lib/nxt_registry.rb
109
- - lib/nxt_registry/attribute.rb
110
109
  - lib/nxt_registry/blank.rb
111
110
  - lib/nxt_registry/errors.rb
112
111
  - lib/nxt_registry/recursive_registry.rb
@@ -122,7 +121,7 @@ metadata:
122
121
  allowed_push_host: https://rubygems.org
123
122
  homepage_uri: https://github.com/nxt-insurance
124
123
  source_code_uri: https://github.com/nxt-insurance/nxt_registry
125
- post_install_message:
124
+ post_install_message:
126
125
  rdoc_options: []
127
126
  require_paths:
128
127
  - lib
@@ -137,8 +136,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
137
136
  - !ruby/object:Gem::Version
138
137
  version: '0'
139
138
  requirements: []
140
- rubygems_version: 3.0.3
141
- signing_key:
139
+ rubygems_version: 3.2.15
140
+ signing_key:
142
141
  specification_version: 4
143
142
  summary: nxt_registry is a simple implementation of the container pattern
144
143
  test_files: []
@@ -1,17 +0,0 @@
1
- module NxtRegistry
2
- class Attribute
3
- def initialize(name, registry, **options)
4
- @name = name
5
- @registry = registry
6
- @namespace = [name, registry.send(:namespace)].join('.')
7
- end
8
-
9
- def eql?(other)
10
- { name => registry.object_id } == { other.send(:name) => other.send(:registry).object_id }
11
- end
12
-
13
- private
14
-
15
- attr_reader :name, :registry
16
- end
17
- end