nxt_registry 0.2.1 → 0.3.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 +14 -0
- data/Gemfile.lock +3 -3
- data/README.md +83 -77
- data/lib/nxt_registry.rb +17 -4
- data/lib/nxt_registry/recursive_registry.rb +1 -1
- data/lib/nxt_registry/registry.rb +54 -21
- data/lib/nxt_registry/{nested_registry_builder.rb → registry_builder.rb} +1 -1
- data/lib/nxt_registry/version.rb +1 -1
- metadata +3 -4
- data/lib/nxt_registry/singleton.rb +0 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 84faa74573904a66ff0f574195ef5ab7e74508d097f04d1e7f43afcfe4867432
|
4
|
+
data.tar.gz: 8f5c04f6eef2f3b7328567d2b1e49fe9e862d915b572e18fdefd32cb71c24fc2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 293d5d1d418152c704ea04aaff4dd392b901c40a9460f1858e5cf6581a0c6fe58041bbe163b8aff3fbcdd9848638f7715e87046b14666f5111677c5241d67eea
|
7
|
+
data.tar.gz: 0475b0d48a589d90ff548d2c7f414bab38e5360fb46cafee35a29e83203a72fcd8fbce4870fbd7862b182ac38558f48567417808c5d400f4a728ff7dbf353a53
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
# v0.3.0 2020-09-10
|
2
|
+
|
3
|
+
### Breaking Changes
|
4
|
+
|
5
|
+
- Toggled interface for resolve(!) and register(!)
|
6
|
+
- Allow to register values in nested registries
|
7
|
+
- Rename nested method into level
|
8
|
+
- Provide registry readers
|
9
|
+
- Remove Singleton extension
|
10
|
+
- Allow to resolve paths
|
11
|
+
- Pass key to default block when it takes an argument
|
12
|
+
|
13
|
+
[Compare v0.2.1...v0.3.0](https://github.com/nxt-insurance/nxt_registry/compare/v0.2.1...v0.3.0)
|
14
|
+
|
1
15
|
# v0.2.1 2020-08-14
|
2
16
|
|
3
17
|
### Fixed
|
data/Gemfile.lock
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
nxt_registry (0.
|
4
|
+
nxt_registry (0.3.0)
|
5
5
|
activesupport
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
9
9
|
specs:
|
10
|
-
activesupport (6.0.3.
|
10
|
+
activesupport (6.0.3.3)
|
11
11
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
12
12
|
i18n (>= 0.7, < 2)
|
13
13
|
minitest (~> 5.1)
|
@@ -19,7 +19,7 @@ GEM
|
|
19
19
|
i18n (1.8.5)
|
20
20
|
concurrent-ruby (~> 1.0)
|
21
21
|
method_source (1.0.0)
|
22
|
-
minitest (5.14.
|
22
|
+
minitest (5.14.2)
|
23
23
|
pry (0.13.1)
|
24
24
|
coderay (~> 1.1)
|
25
25
|
method_source (~> 1.0)
|
data/README.md
CHANGED
@@ -2,8 +2,8 @@
|
|
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 implementation of the container pattern. It allows you to register and resolve values in nested
|
6
|
+
structures.
|
7
7
|
|
8
8
|
## Installation
|
9
9
|
|
@@ -23,61 +23,28 @@ Or install it yourself as:
|
|
23
23
|
|
24
24
|
## Usage
|
25
25
|
|
26
|
-
###
|
26
|
+
### Simple use case
|
27
|
+
|
28
|
+
## Instance Level
|
29
|
+
|
30
|
+
To use `NxtRegistry` on an instance level simply include it and build registries like so:
|
27
31
|
|
28
32
|
```ruby
|
29
33
|
class Example
|
30
34
|
include NxtRegistry
|
31
35
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
nested :via, memoize: true, call: true, default: -> { [] } do
|
37
|
-
attrs %i[train car plane horse] # restrict the attributes that can be registered
|
38
|
-
resolver ->(value) { value } # do something with your registered value here
|
39
|
-
transform_keys ->(key) { key.upcase } # transform keys
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
36
|
+
registry :languages do
|
37
|
+
register(:ruby, 'Stone')
|
38
|
+
register(:python, 'Snake')
|
39
|
+
register(:javascript, 'undefined')
|
44
40
|
end
|
45
41
|
end
|
46
42
|
|
47
43
|
example = Example.new
|
48
|
-
|
49
|
-
# that allows you to resolve and register values by name
|
50
|
-
|
51
|
-
# Register an array with a value by calling the accessor with a key, value pair
|
52
|
-
example.passengers.from(:a).to(:b).via(:train, ['Andy']) # => ['Andy']
|
53
|
-
|
54
|
-
# In case you try to register the same key again you will get an error
|
55
|
-
example.passengers.from(:a).to(:b).via(:train, ['Andy'])
|
56
|
-
# => NxtRegistry::Errors::KeyAlreadyRegisteredError
|
57
|
-
# (Key 'train' already registered in registry 'from.to.via')
|
58
|
-
# NxtRegistry::Errors::KeyAlreadyRegisteredError inherits from KeyError
|
59
|
-
|
60
|
-
# You can force values on the registry by using the bang method
|
61
|
-
example.passengers.from(:a).to(:b).via!(:train, ['Andreas'])
|
62
|
-
|
63
|
-
# Similarly you can try to resolve values softly
|
64
|
-
# (meaning no KeyNotRegisteredError will be raised when nothing was registered)
|
65
|
-
example.passengers.from(:a).to(:b).via!(:train)
|
66
|
-
# Since there is a default defined for this registry, it does not make any sense
|
67
|
-
# since there is always a value. But you get the point...
|
68
|
-
|
69
|
-
# Resolve values by calling the accessor with the key only
|
70
|
-
# In this case the default is returned because nothing was registered yet
|
71
|
-
example.passengers.from(:a).to(:b).via(:hyperloop) # []
|
72
|
-
|
73
|
-
# Appending values to a default array
|
74
|
-
example.passengers.from(:a).to(:b).via(:car) << 'Lütfi' # => ['Lütif']
|
75
|
-
example.passengers.from(:a).to(:b).via(:plane) += %w[Nils Rapha]
|
76
|
-
example.passengers.from(:a).to(:b).via(:plane) # => ['Nils', 'Rapha']
|
77
|
-
|
44
|
+
example.registry(:languages).resolve(:ruby) # => 'Stone'
|
78
45
|
```
|
79
46
|
|
80
|
-
Alternatively you can create
|
47
|
+
Alternatively you can also create instances of `NxtRegistry::Registry`
|
81
48
|
|
82
49
|
```ruby
|
83
50
|
registry = NxtRegistry::Registry.new do
|
@@ -90,52 +57,90 @@ registry.resolve(:aki) # => 'Aki'
|
|
90
57
|
|
91
58
|
```
|
92
59
|
|
93
|
-
|
60
|
+
## Class Level
|
61
|
+
|
62
|
+
You can register registries on the class level simply by extending your class with `NxtRegistry`
|
94
63
|
|
95
64
|
```ruby
|
96
|
-
class
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
registry do
|
101
|
-
# procs are called directly if not defined otherwise
|
65
|
+
class OtherExample
|
66
|
+
extend NxtRegistry
|
67
|
+
|
68
|
+
registry(:errors) do
|
102
69
|
register(KeyError, ->(error) { puts 'KeyError handler' } )
|
103
70
|
register(ArgumentError, ->(error) { puts 'ArgumentError handler' } )
|
104
|
-
# Custom key error handlers
|
105
|
-
on_key_already_registered ->(key) { raise "Key was already registered dude: #{key}" }
|
106
|
-
on_key_not_registered ->(key) { raise "Key was never registered dude: #{key}" }
|
107
71
|
end
|
72
|
+
|
73
|
+
registry(:country_codes) do
|
74
|
+
register(:germany, :de)
|
75
|
+
register(:england, :uk)
|
76
|
+
register(:france, :fr)
|
77
|
+
end
|
108
78
|
end
|
109
|
-
|
110
|
-
|
111
|
-
# Alternatively: SimpleExample.registry.resolve(KeyError)
|
112
|
-
# Or: SimpleExample.instance.resolve(KeyError)
|
79
|
+
|
80
|
+
OtherExample.registry(:errors).resolve(KeyError)
|
113
81
|
# KeyError handler
|
114
82
|
# => nil
|
115
|
-
|
83
|
+
OtherExample.registry(:country_codes).resolve(:germany)
|
84
|
+
# => :de
|
116
85
|
```
|
86
|
+
### Readers
|
87
|
+
|
88
|
+
Access your defined registries with the `registry(:country_code)` method.
|
89
|
+
|
90
|
+
### Nesting registries
|
91
|
+
|
92
|
+
You can also simply nest registries like so:
|
117
93
|
|
118
94
|
```ruby
|
119
|
-
class
|
95
|
+
class Nested
|
120
96
|
extend NxtRegistry
|
121
97
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
98
|
+
registry :developers do
|
99
|
+
register(:frontend) do
|
100
|
+
register(:igor, 'Igor')
|
101
|
+
register(:ben, 'Ben')
|
102
|
+
end
|
103
|
+
|
104
|
+
register(:backend) do
|
105
|
+
register(:rapha, 'Rapha')
|
106
|
+
register(:aki, 'Aki')
|
107
|
+
end
|
127
108
|
end
|
128
109
|
end
|
129
110
|
|
130
|
-
|
131
|
-
#
|
132
|
-
# use register! and resolve! to softly resolve or forcfully register values.
|
133
|
-
OtherExample::REGISTRY.resolve(KeyError)
|
134
|
-
# KeyError handler
|
135
|
-
# => nil
|
136
|
-
|
111
|
+
Nested.registry(:developers).resolve(:frontend, :igor)
|
112
|
+
# => 'Igor'
|
137
113
|
```
|
138
114
|
|
115
|
+
|
116
|
+
### Defining specific nesting levels of a registry
|
117
|
+
|
118
|
+
Another feature of `NxtRegistry` is that you can define the nesting levels for a registry. Levels allow you to dynamically
|
119
|
+
register values within the defined levels. This means that on any level the registry will resolve to another registry and
|
120
|
+
you can register values into a deeply nested structure.
|
121
|
+
|
122
|
+
```ruby
|
123
|
+
class Layer
|
124
|
+
extend NxtRegistry
|
125
|
+
|
126
|
+
registry :from do
|
127
|
+
level :to do
|
128
|
+
level :via
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
Layer.registry(:from) # => Registry[from]
|
134
|
+
|
135
|
+
Layer.registry(:from).resolve(:munich) # => Registry[to] -> {}
|
136
|
+
Layer.registry(:from).resolve(:amsterdam) # => Registry[to] -> {}
|
137
|
+
Layer.registry(:from).resolve(:any_key) # => Registry[to] -> {}
|
138
|
+
|
139
|
+
Layer.registry(:from).resolve(:munich, :amsterdam) # => Registry[via] -> {}
|
140
|
+
Layer.registry(:from).resolve(:munich, :amsterdam).register(:train, -> { 'train' })
|
141
|
+
Layer.registry(:from).resolve(:munich, :amsterdam, :train) # => 'train'
|
142
|
+
```
|
143
|
+
|
139
144
|
### Restrict attributes to a certain set
|
140
145
|
|
141
146
|
Use `attrs` to restrict which attributes can be registered on a specific level.
|
@@ -197,9 +202,10 @@ registry.resolve(:one)
|
|
197
202
|
|
198
203
|
### Transform keys
|
199
204
|
|
200
|
-
NxtRegistry uses a plain ruby hash to store values internally. Per default all keys used are transformed with `&:to_s`.
|
201
|
-
Thus you can use symbols or strings to register and resolve values. If it's not what you want, switch it off with
|
202
|
-
or define your own key transformer by assigning a block to transform_keys:
|
205
|
+
`NxtRegistry` uses a plain ruby hash to store values internally. Per default all keys used are transformed with `&:to_s`.
|
206
|
+
Thus you can use symbols or strings to register and resolve values. If it's not what you want, switch it off with
|
207
|
+
`transform_keys false` or define your own key transformer by assigning a block to transform_keys:
|
208
|
+
`transform_keys ->(key) { key.upcase }`
|
203
209
|
|
204
210
|
```ruby
|
205
211
|
registry :example do
|
data/lib/nxt_registry.rb
CHANGED
@@ -3,17 +3,30 @@ require "nxt_registry/version"
|
|
3
3
|
require "nxt_registry/blank"
|
4
4
|
require "nxt_registry/attribute"
|
5
5
|
require "nxt_registry/errors"
|
6
|
-
require "nxt_registry/
|
6
|
+
require "nxt_registry/registry_builder"
|
7
7
|
require "nxt_registry/registry"
|
8
8
|
require "nxt_registry/recursive_registry"
|
9
|
-
require "nxt_registry/singleton"
|
10
9
|
|
11
10
|
module NxtRegistry
|
12
11
|
def registry(name, **options, &config)
|
13
|
-
|
12
|
+
return registries.fetch(name) if registries.key?(name)
|
13
|
+
|
14
|
+
registry = Registry.new(name, **options, &config)
|
15
|
+
registries[name] ||= registry
|
16
|
+
registry
|
14
17
|
end
|
15
18
|
|
16
19
|
def recursive_registry(name, **options, &config)
|
17
|
-
|
20
|
+
return registries.fetch(name) if registries.key?(name)
|
21
|
+
|
22
|
+
registry = RecursiveRegistry.new(name, **options, &config)
|
23
|
+
registries[name] ||= registry
|
24
|
+
registry
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def registries
|
30
|
+
@registries ||= {}
|
18
31
|
end
|
19
32
|
end
|
@@ -18,7 +18,7 @@ module NxtRegistry
|
|
18
18
|
attr_reader :options, :config, :level
|
19
19
|
|
20
20
|
def set_nested_builder_as_default
|
21
|
-
self.default =
|
21
|
+
self.default = RegistryBuilder.new do
|
22
22
|
RecursiveRegistry.new("level_#{(level + 1)}", **options.merge(level: (level + 1)), &config)
|
23
23
|
end
|
24
24
|
end
|
@@ -16,25 +16,35 @@ module NxtRegistry
|
|
16
16
|
|
17
17
|
attr_reader :name
|
18
18
|
|
19
|
-
def
|
20
|
-
# TODO: Ensure that nesting is included in defined attrs
|
19
|
+
def level(name, **options, &config)
|
21
20
|
options = options.merge(parent: self)
|
22
21
|
|
23
22
|
if default.is_a?(Blank)
|
24
23
|
self.is_leaf = false
|
25
24
|
|
26
|
-
self.default =
|
25
|
+
self.default = RegistryBuilder.new do
|
27
26
|
Registry.new(name, **options, &config)
|
28
27
|
end
|
29
28
|
|
29
|
+
# Call the builder once to guarantee we do not create a registry with a broken setup
|
30
30
|
default.call
|
31
|
-
elsif default.is_a?(
|
31
|
+
elsif default.is_a?(RegistryBuilder)
|
32
32
|
raise ArgumentError, 'Multiple nestings on the same level'
|
33
33
|
else
|
34
34
|
raise ArgumentError, 'Default values cannot be defined on registries that nest others'
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
+
def registry(name, **options, &config)
|
39
|
+
options = options.merge(parent: self)
|
40
|
+
register(name, Registry.new(name, **options, &config))
|
41
|
+
end
|
42
|
+
|
43
|
+
def registry!(name, **options, &config)
|
44
|
+
options = options.merge(parent: self)
|
45
|
+
register!(name, Registry.new(name, **options, &config))
|
46
|
+
end
|
47
|
+
|
38
48
|
def attr(name)
|
39
49
|
key = transformed_key(name)
|
40
50
|
raise KeyError, "Attribute #{key} already registered in #{namespace}" if attrs[key]
|
@@ -49,20 +59,40 @@ module NxtRegistry
|
|
49
59
|
args.each { |name| attr(name) }
|
50
60
|
end
|
51
61
|
|
52
|
-
def register(key, value)
|
53
|
-
|
62
|
+
def register(key = Blank.new, value = Blank.new, **options, &block)
|
63
|
+
if block_given?
|
64
|
+
if value.is_a?(Blank)
|
65
|
+
registry(key, **options, &block)
|
66
|
+
else
|
67
|
+
raise_register_argument_error
|
68
|
+
end
|
69
|
+
else
|
70
|
+
__register(key, value, raise: true)
|
71
|
+
end
|
54
72
|
end
|
55
73
|
|
56
|
-
def register!(key, value)
|
57
|
-
|
74
|
+
def register!(key = Blank.new, value = Blank.new, **options, &block)
|
75
|
+
if block_given?
|
76
|
+
if value.is_a?(Blank)
|
77
|
+
registry!(key, **options, &block)
|
78
|
+
else
|
79
|
+
raise_register_argument_error
|
80
|
+
end
|
81
|
+
else
|
82
|
+
__register(key, value, raise: false)
|
83
|
+
end
|
58
84
|
end
|
59
85
|
|
60
|
-
def resolve(
|
61
|
-
|
86
|
+
def resolve!(*keys)
|
87
|
+
keys.inject(self) do |current_registry, key|
|
88
|
+
current_registry.send(:__resolve, key, raise: true)
|
89
|
+
end
|
62
90
|
end
|
63
91
|
|
64
|
-
def resolve
|
65
|
-
|
92
|
+
def resolve(*keys)
|
93
|
+
keys.inject(self) do |current_registry, key|
|
94
|
+
current_registry.send(:__resolve, key, raise: false) || break
|
95
|
+
end
|
66
96
|
end
|
67
97
|
|
68
98
|
def to_h
|
@@ -70,11 +100,11 @@ module NxtRegistry
|
|
70
100
|
end
|
71
101
|
|
72
102
|
def [](key)
|
73
|
-
|
103
|
+
resolve!(key)
|
74
104
|
end
|
75
105
|
|
76
106
|
def []=(key, value)
|
77
|
-
|
107
|
+
register(key, value)
|
78
108
|
end
|
79
109
|
|
80
110
|
def keys
|
@@ -97,7 +127,7 @@ module NxtRegistry
|
|
97
127
|
store.fetch(transformed_key(key), *args, &block)
|
98
128
|
end
|
99
129
|
|
100
|
-
delegate :size, :values, :each, to: :store
|
130
|
+
delegate :size, :values, :each, :freeze, to: :store
|
101
131
|
|
102
132
|
def configure(&block)
|
103
133
|
define_accessors
|
@@ -131,7 +161,7 @@ module NxtRegistry
|
|
131
161
|
def __register(key, value, raise: true)
|
132
162
|
key = transformed_key(key)
|
133
163
|
|
134
|
-
raise ArgumentError,
|
164
|
+
raise ArgumentError, "Not allowed to register values in a registry that contains nested registries" unless is_leaf
|
135
165
|
raise KeyError, "Keys are restricted to #{attrs.keys}" if attribute_not_allowed?(key)
|
136
166
|
|
137
167
|
on_key_already_registered && on_key_already_registered.call(key) if store[key] && raise
|
@@ -143,7 +173,7 @@ module NxtRegistry
|
|
143
173
|
key = transformed_key(key)
|
144
174
|
|
145
175
|
value = if is_leaf?
|
146
|
-
if store
|
176
|
+
if store.key?(key)
|
147
177
|
store.fetch(key)
|
148
178
|
else
|
149
179
|
if default.is_a?(Blank)
|
@@ -151,14 +181,13 @@ module NxtRegistry
|
|
151
181
|
|
152
182
|
on_key_not_registered && on_key_not_registered.call(key)
|
153
183
|
else
|
154
|
-
value = resolve_default
|
184
|
+
value = resolve_default(key)
|
155
185
|
return value unless memoize
|
156
186
|
|
157
187
|
store[key] ||= value
|
158
188
|
end
|
159
189
|
end
|
160
190
|
else
|
161
|
-
# Call nested registry builder when we are not a leaf
|
162
191
|
store[key] ||= default.call
|
163
192
|
end
|
164
193
|
|
@@ -236,9 +265,9 @@ module NxtRegistry
|
|
236
265
|
attrs.keys.exclude?(transformed_key(key))
|
237
266
|
end
|
238
267
|
|
239
|
-
def resolve_default
|
268
|
+
def resolve_default(key)
|
240
269
|
if call && default.respond_to?(:call)
|
241
|
-
default.call
|
270
|
+
default.arity > 0 ? default.call(key) : default.call
|
242
271
|
else
|
243
272
|
default
|
244
273
|
end
|
@@ -272,5 +301,9 @@ module NxtRegistry
|
|
272
301
|
def build_namespace
|
273
302
|
parent ? name.to_s.prepend("#{parent.send(:namespace)}.") : name.to_s
|
274
303
|
end
|
304
|
+
|
305
|
+
def raise_register_argument_error
|
306
|
+
raise ArgumentError, 'Either provide a key value pair or a block to register'
|
307
|
+
end
|
275
308
|
end
|
276
309
|
end
|
data/lib/nxt_registry/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nxt_registry
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andreas Robecke
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: exe
|
13
13
|
cert_chain: []
|
14
|
-
date: 2020-
|
14
|
+
date: 2020-09-17 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: activesupport
|
@@ -108,10 +108,9 @@ files:
|
|
108
108
|
- lib/nxt_registry/attribute.rb
|
109
109
|
- lib/nxt_registry/blank.rb
|
110
110
|
- lib/nxt_registry/errors.rb
|
111
|
-
- lib/nxt_registry/nested_registry_builder.rb
|
112
111
|
- lib/nxt_registry/recursive_registry.rb
|
113
112
|
- lib/nxt_registry/registry.rb
|
114
|
-
- lib/nxt_registry/
|
113
|
+
- lib/nxt_registry/registry_builder.rb
|
115
114
|
- lib/nxt_registry/version.rb
|
116
115
|
- nxt_registry.gemspec
|
117
116
|
homepage: https://github.com/nxt-insurance
|
@@ -1,17 +0,0 @@
|
|
1
|
-
module NxtRegistry
|
2
|
-
module Singleton
|
3
|
-
def self.extended(subclass)
|
4
|
-
subclass.singleton_class.class_eval do
|
5
|
-
default_name = (subclass.name || 'registry')
|
6
|
-
|
7
|
-
define_method :registry do |name = default_name, **options, &block|
|
8
|
-
@registry ||= NxtRegistry::Registry.new(name, **options, &block)
|
9
|
-
end
|
10
|
-
|
11
|
-
delegate_missing_to :registry
|
12
|
-
|
13
|
-
define_method(:instance) { registry }
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|