nxt_registry 0.3.3 → 0.3.9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1f83b8d92a02103b69d4746dfb08e396d827992bc1d1ef21d39fd46d117ce2ac
4
- data.tar.gz: ab40f633dbed120132de18dbec3b1707c2cab85114ff5857330add4845db0209
3
+ metadata.gz: 9d8d5b1247dfc045e077ccf9d79cf3ea010c9c56434133f8210f3b77af439d0d
4
+ data.tar.gz: 9bd0fc656681a64856f6f21996914ebdeca063ea7cd5585746c29840c4f9694e
5
5
  SHA512:
6
- metadata.gz: 9f843eec28980bd3ffd49906b0661cdce4a02f4a027cf48845cfff799fcbd58213260790501a104435ec71b7e7261f9ff49239dd1296af1f40dcec383de99a29
7
- data.tar.gz: 71cb8513d2eb829bf930a96e244bc6914dbc9f62a78e5fa7916ffc0710765c6393063b055779d22226d718bc52c52fd106f7a3ed8ad44536768a58f28968fe56
6
+ metadata.gz: c136e4279f1fe2907e43ff24f96a28bdec6cf3b095842831c6a1834b468d174e138a370ede137cd318f879c23579c5664a93c5820e7409b6985d4829f7905f30
7
+ data.tar.gz: 2793ac826854219b0e5017e84264ce3908b28c1c9148cddef1dd37dc70b761445ab07d7bd7185f5f2cd58a220cdc1bcb065f6fe49e359a1716922db85fe4532f
data/CHANGELOG.md CHANGED
@@ -1,3 +1,22 @@
1
+ # v0.3.9 2021-03-10
2
+
3
+ - Synchronize access with Mutex
4
+ - Add key_resolver
5
+ - Fix: Inherit options set through accessors
6
+
7
+ # v0.3.5 2020-12-23
8
+
9
+ - Allow to inherit options in nested registries
10
+
11
+ # v0.3.5 2020-12-04
12
+
13
+ - Allow patterns as keys
14
+
15
+ # v0.3.4 2020-12-04
16
+
17
+ - Bring back Singleton
18
+ - Fix mistakes in readme
19
+
1
20
  # v0.3.3 2020-11-24
2
21
 
3
22
  - Fix: Pass key to resolver instead of value
data/Gemfile.lock CHANGED
@@ -1,26 +1,26 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- nxt_registry (0.3.3)
4
+ nxt_registry (0.3.9)
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)
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.9)
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.0)
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)
45
- zeitwerk (2.4.1)
42
+ tzinfo (2.0.4)
43
+ concurrent-ruby (~> 1.0)
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
 
@@ -27,24 +26,23 @@ Or install it yourself as:
27
26
 
28
27
  ## Instance Level
29
28
 
30
- To use `NxtRegistry` on an instance level simply include it and build registries like so:
29
+ If you simply need a single global instance of a registry include `NxtRegistry::Singleton`:
31
30
 
32
31
  ```ruby
33
32
  class Example
34
- include NxtRegistry
33
+ include NxtRegistry::Singleton
35
34
 
36
- registry :languages do
35
+ registry do
37
36
  register(:ruby, 'Stone')
38
37
  register(:python, 'Snake')
39
38
  register(:javascript, 'undefined')
40
39
  end
41
40
  end
42
41
 
43
- example = Example.new
44
- example.registry(:languages).resolve(:ruby) # => 'Stone'
42
+ Example.resolve(:ruby) # => 'Stone'
45
43
  ```
46
44
 
47
- Alternatively you can also create instances of `NxtRegistry::Registry`
45
+ Alternatively you can simply create instances of `NxtRegistry::Registry`:
48
46
 
49
47
  ```ruby
50
48
  registry = NxtRegistry::Registry.new do
@@ -59,7 +57,7 @@ registry.resolve(:aki) # => 'Aki'
59
57
 
60
58
  ## Class Level
61
59
 
62
- You can add registries on the class level simply by extending your class with `NxtRegistry`
60
+ You can also add registries on the class level simply by extending your class with `NxtRegistry`
63
61
 
64
62
  ```ruby
65
63
  class OtherExample
@@ -83,6 +81,30 @@ OtherExample.registry(:errors).resolve(KeyError)
83
81
  OtherExample.registry(:country_codes).resolve(:germany)
84
82
  # => :de
85
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
+
86
108
  ### Readers
87
109
 
88
110
  Access your defined registries with the `registry(:country_code)` method.
@@ -112,6 +134,23 @@ Nested.registry(:developers).resolve(:frontend, :igor)
112
134
  # => 'Igor'
113
135
  ```
114
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
+ ```
115
154
 
116
155
  ### Defining specific nesting levels of a registry
117
156
 
@@ -165,12 +204,21 @@ Layer.registry(:path).from(:munich).to(:amsterdam).via(:train) # => 'train'
165
204
 
166
205
  *Note that this feature is also available for registries with a single level only.*
167
206
 
168
- ### Restrict attributes to a certain set
207
+ ### Restrict keys to a certain set
169
208
 
170
- 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.
171
210
 
172
211
  ```ruby
173
- 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]
174
222
  ```
175
223
 
176
224
  ### Default values
@@ -209,19 +257,21 @@ registry.resolve(:one)
209
257
  # => 2020-01-02 23:56:18 +0100
210
258
  ```
211
259
 
212
- ### Resolver
260
+ ### Resolve callbacks
213
261
 
214
- You can register a resolver block if you want to lay hands on your values after they have been resolved.
215
- 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.
216
264
 
217
265
  ```ruby
218
266
  registry :example do
219
- resolver ->(value) { value * 2 }
220
- register(:one, 1)
267
+ key_resolver ->(key) { key.strip }
268
+ resolver ->(value) { value.upcase }
269
+
270
+ register(:input, 'output')
221
271
  end
222
272
 
223
- registry.resolve(:one)
224
- # => 2
273
+ registry.resolve(' input ')
274
+ # => 'OUTPUT'
225
275
  ```
226
276
 
227
277
  ### Transform keys
data/lib/nxt_registry.rb CHANGED
@@ -1,11 +1,12 @@
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'
8
8
  require 'nxt_registry/recursive_registry'
9
+ require 'nxt_registry/singleton'
9
10
 
10
11
  module NxtRegistry
11
12
  def registry(name, **options, &config)
@@ -19,17 +20,17 @@ module NxtRegistry
19
20
  private
20
21
 
21
22
  def build_registry(registry_class, name, **options, &config)
22
- if registries.key?(name)
23
- registry = registries.fetch(name)
23
+ registry = registries.resolve(name)
24
+
25
+ if registry.present?
24
26
  if registry.configured
25
- registry
27
+ return registry
26
28
  else
27
29
  raise_unconfigured_registry_accessed(name)
28
30
  end
29
31
  else
30
32
  registry = registry_class.new(name, **options, &config)
31
- registries[name] ||= registry
32
- registry
33
+ registries.register(name, registry)
33
34
  end
34
35
  end
35
36
 
@@ -38,6 +39,6 @@ module NxtRegistry
38
39
  end
39
40
 
40
41
  def registries
41
- @registries ||= {}
42
+ @registries ||= Registry.new(:registries)
42
43
  end
43
44
  end
@@ -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,71 +162,110 @@ 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)
177
- key = transformed_key(key)
208
+ mutex.synchronize do
209
+ key = transformed_key(key)
178
210
 
179
- value = if is_leaf?
180
- if store.key?(key)
181
- store.fetch(key)
182
- else
183
- if is_a_blank?(default)
184
- return unless raise_on_key_not_registered
211
+ value = if is_leaf?
212
+ resolved_key = key_resolver.call(key)
185
213
 
186
- on_key_not_registered && on_key_not_registered.call(key)
214
+ if store.key?(resolved_key)
215
+ store.fetch(resolved_key)
216
+ elsif (pattern = matching_pattern(resolved_key))
217
+ store.fetch(pattern)
187
218
  else
188
- value = resolve_default(key)
189
- return value unless memoize
219
+ if is_a_blank?(default)
220
+ return unless raise_on_key_not_registered
221
+
222
+ on_key_not_registered && on_key_not_registered.call(key)
223
+ else
224
+ value = resolve_default(key)
225
+ return value unless memoize
190
226
 
191
- store[key] ||= value
227
+ store[key] ||= value
228
+ end
192
229
  end
230
+ else
231
+ store[key] ||= default.call
193
232
  end
194
- else
195
- store[key] ||= default.call
196
- 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
236
  resolver.call(value)
206
- else
207
- value
208
237
  end
209
238
  end
210
239
 
240
+ def matching_key(key)
241
+ key = transformed_key(key)
242
+ # if key is present it always wins over patterns
243
+ return key if store.key?(key)
244
+
245
+ matching_pattern(key) || key
246
+ end
247
+
248
+ def call_or_value(value, key)
249
+ return value unless call
250
+ return value if value.is_a?(NxtRegistry::Registry)
251
+ return value unless value.respond_to?(:call)
252
+
253
+ args = [key, value]
254
+ value.call(*args.take(value.arity))
255
+ end
256
+
257
+ def matching_pattern(key)
258
+ patterns.find { |pattern| key.match?(pattern) }
259
+ end
260
+
211
261
  def define_interface
212
262
  return if interface_defined
213
263
 
214
- raise_invalid_accessor_name(accessor) if respond_to?(accessor)
264
+ raise_invalid_accessor_name(accessor) if respond_to?(accessor.to_s)
215
265
  accessor_with_bang = "#{accessor}!"
216
266
  raise_invalid_accessor_name(accessor_with_bang) if respond_to?(accessor_with_bang)
217
267
 
218
- define_singleton_method accessor do |key = Blank.new, value = Blank.new|
268
+ define_singleton_method accessor.to_s do |key = Blank.new, value = Blank.new|
219
269
  return self if is_a_blank?(key)
220
270
 
221
271
  key = transformed_key(key)
@@ -246,8 +296,9 @@ module NxtRegistry
246
296
  @default = options.fetch(:default) { Blank.new }
247
297
  @memoize = options.fetch(:memoize) { true }
248
298
  @call = options.fetch(:call) { true }
249
- @resolver = options.fetch(:resolver, false)
250
- @transform_keys = options.fetch(:transform_keys) { ->(key) { key.to_s } }
299
+ @resolver = options.fetch(:resolver, ->(val) { val })
300
+ @key_resolver = options.fetch(:key_resolver, ->(val) { val })
301
+ @transform_keys = options.fetch(:transform_keys) { ->(key) { key.is_a?(Regexp) ? key : key.to_s } }
251
302
  @accessor = options.fetch(:accessor) { name }
252
303
 
253
304
  @on_key_already_registered = options.fetch(:on_key_already_registered) { ->(key) { raise_key_already_registered_error(key) } }
@@ -255,27 +306,29 @@ module NxtRegistry
255
306
  end
256
307
 
257
308
  def define_accessors
258
- %w[default memoize call resolver transform_keys on_key_already_registered on_key_not_registered].each do |attribute|
309
+ %w[default memoize call resolver key_resolver transform_keys on_key_already_registered on_key_not_registered].each do |attribute|
259
310
  define_singleton_method attribute do |value = Blank.new, &block|
260
311
  value = block if block
261
312
 
262
313
  if is_a_blank?(value)
263
314
  instance_variable_get("@#{attribute}")
264
315
  else
316
+ options[attribute.to_sym] ||= value
265
317
  instance_variable_set("@#{attribute}", value)
266
318
  end
267
319
  end
268
320
 
269
321
  define_singleton_method "#{attribute}=" do |value|
322
+ options[attribute.to_sym] ||= value
270
323
  instance_variable_set("@#{attribute}", value)
271
324
  end
272
325
  end
273
326
  end
274
327
 
275
- def attribute_not_allowed?(key)
276
- return if attrs.empty?
328
+ def key_not_allowed?(key)
329
+ return if allowed_keys.empty?
277
330
 
278
- attrs.keys.exclude?(transformed_key(key))
331
+ allowed_keys.exclude?(transformed_key(key))
279
332
  end
280
333
 
281
334
  def resolve_default(key)
@@ -305,12 +358,6 @@ module NxtRegistry
305
358
  end
306
359
  end
307
360
 
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
361
  def build_namespace
315
362
  parent ? name.to_s.prepend("#{parent.send(:namespace)}.") : name.to_s
316
363
  end
@@ -326,5 +373,16 @@ module NxtRegistry
326
373
  def raise_invalid_accessor_name(name)
327
374
  raise ArgumentError, "#{self} already implements a method named: #{name}. Please choose a different accessor name"
328
375
  end
376
+
377
+ def initialize_copy(original)
378
+ super
379
+
380
+ @mutex = Mutex.new
381
+ containers = %i[store options]
382
+ variables = %i[patterns required_keys allowed_keys namespace on_key_already_registered on_key_not_registered]
383
+
384
+ containers.each { |c| instance_variable_set("@#{c}", original.send(c).deep_dup) }
385
+ variables.each { |v| instance_variable_set("@#{v}", original.send(v).dup) }
386
+ end
329
387
  end
330
388
  end
@@ -0,0 +1,15 @@
1
+ module NxtRegistry
2
+ module Singleton
3
+ include NxtRegistry
4
+
5
+ def self.included(base)
6
+ base.extend(self)
7
+ end
8
+
9
+ def registry(type = Registry, **options, &config)
10
+ @registry ||= build_registry(type, self.class.name, **options, &config)
11
+ end
12
+
13
+ delegate_missing_to :registry
14
+ end
15
+ end
@@ -1,3 +1,3 @@
1
1
  module NxtRegistry
2
- VERSION = "0.3.3"
2
+ VERSION = '0.3.9'
3
3
  end
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.3.3
4
+ version: 0.3.9
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-11-24 00:00:00.000000000 Z
14
+ date: 2021-03-10 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: activesupport
@@ -106,12 +106,12 @@ 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
113
112
  - lib/nxt_registry/registry.rb
114
113
  - lib/nxt_registry/registry_builder.rb
114
+ - lib/nxt_registry/singleton.rb
115
115
  - lib/nxt_registry/version.rb
116
116
  - nxt_registry.gemspec
117
117
  homepage: https://github.com/nxt-insurance
@@ -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