nxt_registry 0.2.1 → 0.3.0

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: 6851c2c3d6dde7438aa6abe438153d4126ea962f948d472a37d8b958830390f3
4
- data.tar.gz: '02158d50dd9af0686bd4427e1c41853dca588e686b9a02381263c94700093398'
3
+ metadata.gz: 84faa74573904a66ff0f574195ef5ab7e74508d097f04d1e7f43afcfe4867432
4
+ data.tar.gz: 8f5c04f6eef2f3b7328567d2b1e49fe9e862d915b572e18fdefd32cb71c24fc2
5
5
  SHA512:
6
- metadata.gz: 04c65be146020a7e3c1e1fa6587cdb9efb0c4b2ab6d76741855fe99a0246e4a5ace755c3184678164f388d41a45ddc6a03c39298c0038ecf13e454f77a5deb74
7
- data.tar.gz: f992919cf0d07da41e411b7dff32410678b664f4a12a47e350e0d51e239c6864eaeb549aca4518eae1f122640b99274897e6bc4b39bb6889634e6a32ee137931
6
+ metadata.gz: 293d5d1d418152c704ea04aaff4dd392b901c40a9460f1858e5cf6581a0c6fe58041bbe163b8aff3fbcdd9848638f7715e87046b14666f5111677c5241d67eea
7
+ data.tar.gz: 0475b0d48a589d90ff548d2c7f414bab38e5360fb46cafee35a29e83203a72fcd8fbce4870fbd7862b182ac38558f48567417808c5d400f4a728ff7dbf353a53
@@ -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
@@ -1,13 +1,13 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- nxt_registry (0.2.1)
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.2)
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.1)
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 by allowing nesting registries into each other. In theory this can be indefinitely deep.
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
- ### Instance Level
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
- def passengers
33
- @passengers ||= begin
34
- registry :from do
35
- nested :to do
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
- # Based on the naming of the registry and its nesting you are provided with a simple interface
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 an instance of NxtRegistry::Registry.new('name', **options, &config)
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
- ### Class Level
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 SimpleExample
97
- # By extending NxtRegistry::Singleton you get a super simple class level interface to an underlying instance of a :registry
98
- extend NxtRegistry::Singleton
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
- SimpleExample.resolve(KeyError)
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 OtherExample
95
+ class Nested
120
96
  extend NxtRegistry
121
97
 
122
- # By passing a block to :registry you can directly register your values inline
123
- REGISTRY = registry(:errors) do
124
- # procs are called directly if not defined otherwise
125
- register(KeyError, ->(error) { puts 'KeyError handler' } )
126
- register(ArgumentError, ->(error) { puts 'ArgumentError handler' } )
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
- # Instead of using the name of the registry, you can also always call register and resolve on the
131
- # level where you want to register or resolve values. Equivalently to the named interface you can
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 `transform_keys false`
202
- or define your own key transformer by assigning a block to transform_keys: `transform_keys ->(key) { key.upcase }`
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
@@ -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/nested_registry_builder"
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
- Registry.new(name, **options, &config)
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
- RecursiveRegistry.new(name, **options, &config)
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 = NestedRegistryBuilder.new do
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 nested(name, **options, &config)
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 = NestedRegistryBuilder.new do
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?(NestedRegistryBuilder)
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
- __register(key, value, raise: true)
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
- __register(key, value, raise: false)
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(key)
61
- __resolve(key, raise: true)
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!(key)
65
- __resolve(key, raise: false)
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
- store[transformed_key(key)]
103
+ resolve!(key)
74
104
  end
75
105
 
76
106
  def []=(key, value)
77
- store[transformed_key(key)] = value
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, 'Not allowed to register values in a registry that contains nested registries' unless is_leaf
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[key]
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
@@ -1,5 +1,5 @@
1
1
  module NxtRegistry
2
- class NestedRegistryBuilder < Proc
2
+ class RegistryBuilder < Proc
3
3
  def initialize(&block)
4
4
  super(&block)
5
5
  end
@@ -1,3 +1,3 @@
1
1
  module NxtRegistry
2
- VERSION = "0.2.1"
2
+ VERSION = "0.3.0"
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.2.1
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-08-14 00:00:00.000000000 Z
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/singleton.rb
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