nxt_registry 0.3.3 → 0.3.9

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: 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