nxt_registry 0.2.0 → 0.3.3

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: 3643055d95f31f6addec18700fd8d7d9157bc4f97848acef8340c11668cfa3df
4
- data.tar.gz: 25018d4d1f657991137e0c94bf8afacaca70dcd44008ff6cb96783ea82aa064d
3
+ metadata.gz: 1f83b8d92a02103b69d4746dfb08e396d827992bc1d1ef21d39fd46d117ce2ac
4
+ data.tar.gz: ab40f633dbed120132de18dbec3b1707c2cab85114ff5857330add4845db0209
5
5
  SHA512:
6
- metadata.gz: 74aefe510917560c5dbc3686834ce64aeb815e8f67d99718f6abf38dd08d639f9a8bba14f3cd2275f7f790b3b853b0207006888ee9303ed4d4b706e99d6e1d8b
7
- data.tar.gz: 2225edb2af2a5493b90642934d415115a8577043f69fa329bfe99c0676997d4ad68c023c1c79fc1552519a2ed50a5478ebe440ad936ee5832956a27ebad1caec
6
+ metadata.gz: 9f843eec28980bd3ffd49906b0661cdce4a02f4a027cf48845cfff799fcbd58213260790501a104435ec71b7e7261f9ff49239dd1296af1f40dcec383de99a29
7
+ data.tar.gz: 71cb8513d2eb829bf930a96e244bc6914dbc9f62a78e5fa7916ffc0710765c6393063b055779d22226d718bc52c52fd106f7a3ed8ad44536768a58f28968fe56
@@ -1,3 +1,38 @@
1
+ # v0.3.3 2020-11-24
2
+
3
+ - Fix: Pass key to resolver instead of value
4
+
5
+ # v0.3.2 2020-09-29
6
+
7
+ - Fix interface definition
8
+
9
+ # v0.3.1 2020-09-23
10
+
11
+ - Allow to define custom accessors for registries
12
+
13
+ # v0.3.0 2020-09-10
14
+
15
+ ### Breaking Changes
16
+
17
+ - Toggled interface for resolve(!) and register(!)
18
+ - Allow to register values in nested registries
19
+ - Rename nested method into level
20
+ - Provide registry readers
21
+ - Remove Singleton extension
22
+ - Allow to resolve paths
23
+ - Pass key to default block when it takes an argument
24
+
25
+ [Compare v0.2.1...v0.3.0](https://github.com/nxt-insurance/nxt_registry/compare/v0.2.1...v0.3.0)
26
+
27
+ # v0.2.1 2020-08-14
28
+
29
+ ### Fixed
30
+
31
+ - Fixed Registry#fetch to raise key error in case of missing key
32
+
33
+ [Compare v0.2.0...v0.2.1](https://github.com/nxt-insurance/nxt_registry/compare/v0.2.0...v0.2.1)
34
+
35
+
1
36
  # v0.2.0 2020-07-24
2
37
 
3
38
  ### Added
@@ -1,48 +1,48 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- nxt_registry (0.2.0)
4
+ nxt_registry (0.3.3)
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.4)
11
11
  concurrent-ruby (~> 1.0, >= 1.0.2)
12
12
  i18n (>= 0.7, < 2)
13
13
  minitest (~> 5.1)
14
14
  tzinfo (~> 1.1)
15
15
  zeitwerk (~> 2.2, >= 2.2.2)
16
16
  coderay (1.1.3)
17
- concurrent-ruby (1.1.6)
17
+ concurrent-ruby (1.1.7)
18
18
  diff-lcs (1.4.4)
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)
26
26
  rake (12.3.3)
27
- rspec (3.9.0)
28
- rspec-core (~> 3.9.0)
29
- rspec-expectations (~> 3.9.0)
30
- rspec-mocks (~> 3.9.0)
31
- rspec-core (3.9.2)
32
- rspec-support (~> 3.9.3)
33
- rspec-expectations (3.9.2)
27
+ rspec (3.10.0)
28
+ rspec-core (~> 3.10.0)
29
+ rspec-expectations (~> 3.10.0)
30
+ rspec-mocks (~> 3.10.0)
31
+ rspec-core (3.10.0)
32
+ rspec-support (~> 3.10.0)
33
+ rspec-expectations (3.10.0)
34
34
  diff-lcs (>= 1.2.0, < 2.0)
35
- rspec-support (~> 3.9.0)
36
- rspec-mocks (3.9.1)
35
+ rspec-support (~> 3.10.0)
36
+ rspec-mocks (3.10.0)
37
37
  diff-lcs (>= 1.2.0, < 2.0)
38
- rspec-support (~> 3.9.0)
39
- rspec-support (3.9.3)
38
+ rspec-support (~> 3.10.0)
39
+ rspec-support (3.10.0)
40
40
  rspec_junit_formatter (0.4.1)
41
41
  rspec-core (>= 2, < 4, != 2.12.0)
42
42
  thread_safe (0.3.6)
43
- tzinfo (1.2.7)
43
+ tzinfo (1.2.8)
44
44
  thread_safe (~> 0.1)
45
- zeitwerk (2.4.0)
45
+ zeitwerk (2.4.1)
46
46
 
47
47
  PLATFORMS
48
48
  ruby
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,114 @@ registry.resolve(:aki) # => 'Aki'
90
57
 
91
58
  ```
92
59
 
93
- ### Class Level
60
+ ## Class Level
61
+
62
+ You can add 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
111
+ Nested.registry(:developers).resolve(:frontend, :igor)
112
+ # => 'Igor'
113
+ ```
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
+ # On every upper level every resolve returns a registry
134
+ Layer.registry(:from) # => Registry[from]
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
+ Layer.registry(:from).resolve(:munich, :amsterdam) # => Registry[via] -> {}
139
+
140
+ # Register a value on the bottom level
141
+ Layer.registry(:from).resolve(:munich, :amsterdam).register(:train, -> { 'train' })
142
+ # Resolve the complete path
143
+ Layer.registry(:from).resolve(:munich, :amsterdam, :train) # => 'train'
144
+ ```
145
+
146
+ For registries with multiple levels the normal syntax for registering and resolving becomes quite weird and unreadable. This is why
147
+ every registry can be accessed through it's name or a custom accessor. The above example then can be simplified as follows.
148
+
149
+ ```ruby
150
+ class Layer
151
+ extend NxtRegistry
152
+
153
+ registry :path, accessor: :from do # registry named path, can be accessed with .from(...)
154
+ level :to do
155
+ level :via
156
+ end
157
+ end
158
+ end
136
159
 
160
+ # Register a value
161
+ Layer.registry(:path).from(:munich).to(:amsterdam).via(:train, -> { 'train' })
162
+ # Resolve the complete path
163
+ Layer.registry(:path).from(:munich).to(:amsterdam).via(:train) # => 'train'
137
164
  ```
138
165
 
166
+ *Note that this feature is also available for registries with a single level only.*
167
+
139
168
  ### Restrict attributes to a certain set
140
169
 
141
170
  Use `attrs` to restrict which attributes can be registered on a specific level.
@@ -197,9 +226,10 @@ registry.resolve(:one)
197
226
 
198
227
  ### Transform keys
199
228
 
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 }`
229
+ `NxtRegistry` uses a plain ruby hash to store values internally. Per default all keys used are transformed with `&:to_s`.
230
+ Thus you can use symbols or strings to register and resolve values. If it's not what you want, switch it off with
231
+ `transform_keys false` or define your own key transformer by assigning a block to transform_keys:
232
+ `transform_keys ->(key) { key.upcase }`
203
233
 
204
234
  ```ruby
205
235
  registry :example do
@@ -1,19 +1,43 @@
1
1
  require 'active_support/core_ext'
2
- require "nxt_registry/version"
3
- require "nxt_registry/blank"
4
- require "nxt_registry/attribute"
5
- require "nxt_registry/errors"
6
- require "nxt_registry/nested_registry_builder"
7
- require "nxt_registry/registry"
8
- require "nxt_registry/recursive_registry"
9
- require "nxt_registry/singleton"
2
+ require 'nxt_registry/version'
3
+ require 'nxt_registry/blank'
4
+ require 'nxt_registry/attribute'
5
+ require 'nxt_registry/errors'
6
+ require 'nxt_registry/registry_builder'
7
+ require 'nxt_registry/registry'
8
+ require 'nxt_registry/recursive_registry'
10
9
 
11
10
  module NxtRegistry
12
11
  def registry(name, **options, &config)
13
- Registry.new(name, **options, &config)
12
+ build_registry(Registry, name, **options, &config)
14
13
  end
15
14
 
16
15
  def recursive_registry(name, **options, &config)
17
- RecursiveRegistry.new(name, **options, &config)
16
+ build_registry(RecursiveRegistry, name, **options, &config)
17
+ end
18
+
19
+ private
20
+
21
+ def build_registry(registry_class, name, **options, &config)
22
+ if registries.key?(name)
23
+ registry = registries.fetch(name)
24
+ if registry.configured
25
+ registry
26
+ else
27
+ raise_unconfigured_registry_accessed(name)
28
+ end
29
+ else
30
+ registry = registry_class.new(name, **options, &config)
31
+ registries[name] ||= registry
32
+ registry
33
+ end
34
+ end
35
+
36
+ def raise_unconfigured_registry_accessed(name)
37
+ raise ArgumentError, "The registry #{name} must be configured before accessed!"
38
+ end
39
+
40
+ def registries
41
+ @registries ||= {}
18
42
  end
19
43
  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
@@ -1,40 +1,52 @@
1
1
  module NxtRegistry
2
2
  class Registry
3
3
  def initialize(name = object_id.to_s, **options, &config)
4
+ @options = options
4
5
  @name = name
5
6
  @parent = options[:parent]
6
7
  @is_leaf = true
7
- @namespace = parent ? name.to_s.prepend("#{parent.send(:namespace)}.") : name.to_s
8
+ @namespace = build_namespace
8
9
  @config = config
9
- @options = options
10
10
  @store = {}
11
11
  @attrs = nil
12
+ @configured = false
12
13
 
13
14
  setup_defaults(options)
14
15
  configure(&config)
15
16
  end
16
17
 
17
18
  attr_reader :name
19
+ attr_accessor :configured
18
20
 
19
- def nested(name, **options, &config)
20
- # TODO: Ensure that nesting is included in defined attrs
21
+ def level(name, **options, &config)
21
22
  options = options.merge(parent: self)
22
23
 
23
- if default.is_a?(Blank)
24
+ if is_a_blank?(default)
24
25
  self.is_leaf = false
25
26
 
26
- self.default = NestedRegistryBuilder.new do
27
+ self.default = RegistryBuilder.new do
27
28
  Registry.new(name, **options, &config)
28
29
  end
29
30
 
31
+ # Call the builder once to guarantee we do not create a registry with a broken setup
30
32
  default.call
31
- elsif default.is_a?(NestedRegistryBuilder)
32
- raise ArgumentError, "Multiple nestings on the same level"
33
+ elsif default.is_a?(RegistryBuilder)
34
+ raise ArgumentError, 'Multiple nestings on the same level'
33
35
  else
34
- raise ArgumentError, "Default values cannot be defined on registries that nest others"
36
+ raise ArgumentError, 'Default values cannot be defined on registries that nest others'
35
37
  end
36
38
  end
37
39
 
40
+ def registry(name, **options, &config)
41
+ opts = options.merge(parent: self)
42
+ register(name, Registry.new(name, **opts, &config))
43
+ end
44
+
45
+ def registry!(name, **options, &config)
46
+ opts = options.merge(parent: self)
47
+ register!(name, Registry.new(name, **opts, &config))
48
+ end
49
+
38
50
  def attr(name)
39
51
  key = transformed_key(name)
40
52
  raise KeyError, "Attribute #{key} already registered in #{namespace}" if attrs[key]
@@ -49,20 +61,40 @@ module NxtRegistry
49
61
  args.each { |name| attr(name) }
50
62
  end
51
63
 
52
- def register(key, value)
53
- __register(key, value, raise: true)
64
+ def register(key = Blank.new, value = Blank.new, **options, &block)
65
+ if block_given?
66
+ if is_a_blank?(value)
67
+ registry(key, **options, &block)
68
+ else
69
+ raise_register_argument_error
70
+ end
71
+ else
72
+ __register(key, value, raise_on_key_already_registered: true)
73
+ end
54
74
  end
55
75
 
56
- def register!(key, value)
57
- __register(key, value, raise: false)
76
+ def register!(key = Blank.new, value = Blank.new, **options, &block)
77
+ if block_given?
78
+ if is_a_blank?(value)
79
+ registry!(key, **options, &block)
80
+ else
81
+ raise_register_argument_error
82
+ end
83
+ else
84
+ __register(key, value, raise_on_key_already_registered: false)
85
+ end
58
86
  end
59
87
 
60
- def resolve(key)
61
- __resolve(key, raise: true)
88
+ def resolve!(*keys)
89
+ keys.inject(self) do |current_registry, key|
90
+ current_registry.send(:__resolve, key, raise_on_key_not_registered: true)
91
+ end
62
92
  end
63
93
 
64
- def resolve!(key)
65
- __resolve(key, raise: false)
94
+ def resolve(*keys)
95
+ keys.inject(self) do |current_registry, key|
96
+ current_registry.send(:__resolve, key, raise_on_key_not_registered: false) || break
97
+ end
66
98
  end
67
99
 
68
100
  def to_h
@@ -70,11 +102,11 @@ module NxtRegistry
70
102
  end
71
103
 
72
104
  def [](key)
73
- store[transformed_key(key)]
105
+ resolve!(key)
74
106
  end
75
107
 
76
108
  def []=(key, value)
77
- store[transformed_key(key)] = value
109
+ register(key, value)
78
110
  end
79
111
 
80
112
  def keys
@@ -93,11 +125,11 @@ module NxtRegistry
93
125
  store.exclude?(transformed_key(key))
94
126
  end
95
127
 
96
- def fetch(key, **opts, &block)
97
- store.fetch(transformed_key(key), **opts, &block)
128
+ def fetch(key, *args, &block)
129
+ store.fetch(transformed_key(key), *args, &block)
98
130
  end
99
131
 
100
- delegate :size, :values, :each, to: :store
132
+ delegate :size, :values, :each, :freeze, to: :store
101
133
 
102
134
  def configure(&block)
103
135
  define_accessors
@@ -111,6 +143,8 @@ module NxtRegistry
111
143
  instance_exec(&block)
112
144
  end
113
145
  end
146
+
147
+ self.configured = true
114
148
  end
115
149
 
116
150
  def to_s
@@ -121,48 +155,48 @@ module NxtRegistry
121
155
 
122
156
  private
123
157
 
124
- attr_reader :namespace, :parent, :config, :store, :options
125
- attr_accessor :is_leaf
158
+ attr_reader :namespace, :parent, :config, :store, :options, :accessor
159
+ attr_accessor :is_leaf, :interface_defined
126
160
 
127
161
  def is_leaf?
128
162
  @is_leaf
129
163
  end
130
164
 
131
- def __register(key, value, raise: true)
165
+ def __register(key, value, raise_on_key_already_registered: true)
132
166
  key = transformed_key(key)
133
167
 
134
168
  raise ArgumentError, "Not allowed to register values in a registry that contains nested registries" unless is_leaf
135
169
  raise KeyError, "Keys are restricted to #{attrs.keys}" if attribute_not_allowed?(key)
136
- on_key_already_registered && on_key_already_registered.call(key) if store[key] && raise
170
+
171
+ on_key_already_registered && on_key_already_registered.call(key) if store[key] && raise_on_key_already_registered
137
172
 
138
173
  store[key] = value
139
174
  end
140
175
 
141
- def __resolve(key, raise: true)
176
+ def __resolve(key, raise_on_key_not_registered: true)
142
177
  key = transformed_key(key)
143
178
 
144
179
  value = if is_leaf?
145
- if store[key]
180
+ if store.key?(key)
146
181
  store.fetch(key)
147
182
  else
148
- if default.is_a?(Blank)
149
- return unless raise
183
+ if is_a_blank?(default)
184
+ return unless raise_on_key_not_registered
150
185
 
151
186
  on_key_not_registered && on_key_not_registered.call(key)
152
187
  else
153
- value = resolve_default
188
+ value = resolve_default(key)
154
189
  return value unless memoize
155
190
 
156
191
  store[key] ||= value
157
192
  end
158
193
  end
159
194
  else
160
- # Call nested registry builder when we are not a leaf
161
195
  store[key] ||= default.call
162
196
  end
163
197
 
164
198
  value = if value.respond_to?(:call) && call && !value.is_a?(NxtRegistry::Registry)
165
- value.call(*[value].take(value.arity))
199
+ value.call(*[key].take(value.arity))
166
200
  else
167
201
  value
168
202
  end
@@ -175,29 +209,37 @@ module NxtRegistry
175
209
  end
176
210
 
177
211
  def define_interface
178
- define_singleton_method name do |key = Blank.new, value = Blank.new|
179
- return self if key.is_a?(Blank)
212
+ return if interface_defined
213
+
214
+ raise_invalid_accessor_name(accessor) if respond_to?(accessor)
215
+ accessor_with_bang = "#{accessor}!"
216
+ raise_invalid_accessor_name(accessor_with_bang) if respond_to?(accessor_with_bang)
217
+
218
+ define_singleton_method accessor do |key = Blank.new, value = Blank.new|
219
+ return self if is_a_blank?(key)
180
220
 
181
221
  key = transformed_key(key)
182
222
 
183
- if value.is_a?(Blank)
223
+ if is_a_blank?(value)
184
224
  resolve(key)
185
225
  else
186
226
  register(key, value)
187
227
  end
188
228
  end
189
229
 
190
- define_singleton_method "#{name}!" do |key = Blank.new, value = Blank.new|
191
- return self if key.is_a?(Blank)
230
+ define_singleton_method accessor_with_bang do |key = Blank.new, value = Blank.new|
231
+ return self if is_a_blank?(key)
192
232
 
193
233
  key = transformed_key(key)
194
234
 
195
- if value.is_a?(Blank)
235
+ if is_a_blank?(value)
196
236
  resolve!(key)
197
237
  else
198
238
  register!(key, value)
199
239
  end
200
240
  end
241
+
242
+ self.interface_defined = true
201
243
  end
202
244
 
203
245
  def setup_defaults(options)
@@ -206,6 +248,7 @@ module NxtRegistry
206
248
  @call = options.fetch(:call) { true }
207
249
  @resolver = options.fetch(:resolver, false)
208
250
  @transform_keys = options.fetch(:transform_keys) { ->(key) { key.to_s } }
251
+ @accessor = options.fetch(:accessor) { name }
209
252
 
210
253
  @on_key_already_registered = options.fetch(:on_key_already_registered) { ->(key) { raise_key_already_registered_error(key) } }
211
254
  @on_key_not_registered = options.fetch(:on_key_not_registered) { ->(key) { raise_key_not_registered_error(key) } }
@@ -214,10 +257,9 @@ module NxtRegistry
214
257
  def define_accessors
215
258
  %w[default memoize call resolver transform_keys on_key_already_registered on_key_not_registered].each do |attribute|
216
259
  define_singleton_method attribute do |value = Blank.new, &block|
217
- # TODO: Allowing a block does not make sense for memoize and call?!
218
260
  value = block if block
219
261
 
220
- if value.is_a?(Blank)
262
+ if is_a_blank?(value)
221
263
  instance_variable_get("@#{attribute}")
222
264
  else
223
265
  instance_variable_set("@#{attribute}", value)
@@ -236,9 +278,9 @@ module NxtRegistry
236
278
  attrs.keys.exclude?(transformed_key(key))
237
279
  end
238
280
 
239
- def resolve_default
281
+ def resolve_default(key)
240
282
  if call && default.respond_to?(:call)
241
- default.call
283
+ default.arity > 0 ? default.call(key) : default.call
242
284
  else
243
285
  default
244
286
  end
@@ -255,7 +297,7 @@ module NxtRegistry
255
297
  def transformed_key(key)
256
298
  @transformed_key ||= {}
257
299
  @transformed_key[key] ||= begin
258
- if transform_keys && !key.is_a?(Blank)
300
+ if transform_keys && !is_a_blank?(key)
259
301
  transform_keys.call(key)
260
302
  else
261
303
  key
@@ -268,5 +310,21 @@ module NxtRegistry
268
310
  @store = original.send(:store).deep_dup
269
311
  @options = original.send(:options).deep_dup
270
312
  end
313
+
314
+ def build_namespace
315
+ parent ? name.to_s.prepend("#{parent.send(:namespace)}.") : name.to_s
316
+ end
317
+
318
+ def raise_register_argument_error
319
+ raise ArgumentError, 'Either provide a key value pair or a block to register'
320
+ end
321
+
322
+ def is_a_blank?(value)
323
+ value.is_a?(Blank)
324
+ end
325
+
326
+ def raise_invalid_accessor_name(name)
327
+ raise ArgumentError, "#{self} already implements a method named: #{name}. Please choose a different accessor name"
328
+ end
271
329
  end
272
330
  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.0"
2
+ VERSION = "0.3.3"
3
3
  end
@@ -6,7 +6,7 @@ Gem::Specification.new do |spec|
6
6
  spec.name = "nxt_registry"
7
7
  spec.version = NxtRegistry::VERSION
8
8
  spec.authors = ["Andreas Robecke", "Nils Sommer", "Raphael Kallensee", "Lütfi Demirci"]
9
- spec.email = ["a.robecke@getsafe.de"]
9
+ spec.email = ['a.robecke@hellogetsafe.com', 'andreas@robecke.de']
10
10
 
11
11
  spec.summary = %q{nxt_registry is a simple implementation of the container pattern}
12
12
  spec.homepage = "https://github.com/nxt-insurance"
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.0
4
+ version: 0.3.3
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-07-27 00:00:00.000000000 Z
14
+ date: 2020-11-24 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: activesupport
@@ -85,7 +85,8 @@ dependencies:
85
85
  version: '0'
86
86
  description:
87
87
  email:
88
- - a.robecke@getsafe.de
88
+ - a.robecke@hellogetsafe.com
89
+ - andreas@robecke.de
89
90
  executables: []
90
91
  extensions: []
91
92
  extra_rdoc_files: []
@@ -108,10 +109,9 @@ files:
108
109
  - lib/nxt_registry/attribute.rb
109
110
  - lib/nxt_registry/blank.rb
110
111
  - lib/nxt_registry/errors.rb
111
- - lib/nxt_registry/nested_registry_builder.rb
112
112
  - lib/nxt_registry/recursive_registry.rb
113
113
  - lib/nxt_registry/registry.rb
114
- - lib/nxt_registry/singleton.rb
114
+ - lib/nxt_registry/registry_builder.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
- 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