nxt_registry 0.1.3 → 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: a68b0acda862ba1abd86c05b6965258563e4c091bd0ae49012f92d5833ba1416
4
- data.tar.gz: b6d55555232b4fc6fbbd842d538f0732fe5232369be6724525d6723465d6776b
3
+ metadata.gz: 84faa74573904a66ff0f574195ef5ab7e74508d097f04d1e7f43afcfe4867432
4
+ data.tar.gz: 8f5c04f6eef2f3b7328567d2b1e49fe9e862d915b572e18fdefd32cb71c24fc2
5
5
  SHA512:
6
- metadata.gz: 25799005260cfb9bbda4264200c0cc1ea80e6fde0f7671048413f8835d1035f4fa27179a0ec047ca5d555600ec7f0d82cc9ee15a58934159d8b382896300e6af
7
- data.tar.gz: 994fda385124d529b3edc72bfd4c2e2a2186e8e79918b0e1029f0f7ed20bc921024d30f60c0d4df6cc8227fe6738a31a049dc1ff29ad814c1b71a9ba9b60ef4e
6
+ metadata.gz: 293d5d1d418152c704ea04aaff4dd392b901c40a9460f1858e5cf6581a0c6fe58041bbe163b8aff3fbcdd9848638f7715e87046b14666f5111677c5241d67eea
7
+ data.tar.gz: 0475b0d48a589d90ff548d2c7f414bab38e5360fb46cafee35a29e83203a72fcd8fbce4870fbd7862b182ac38558f48567417808c5d400f4a728ff7dbf353a53
@@ -0,0 +1,56 @@
1
+ # Ruby CircleCI 2.0 configuration file
2
+ #
3
+ # Check https://circleci.com/docs/2.0/language-ruby/ for more details
4
+ #
5
+ version: 2
6
+ jobs:
7
+ build:
8
+ docker:
9
+ # specify the version you desire here
10
+ - image: circleci/ruby:2.6.5-node
11
+ environment:
12
+ BUNDLER_VERSION: 2.1.4
13
+
14
+ working_directory: ~/repo
15
+
16
+ steps:
17
+ - checkout
18
+
19
+ # Download and cache dependencies
20
+ - restore_cache:
21
+ keys:
22
+ - v1-dependencies-{{ checksum "Gemfile.lock" }}
23
+
24
+ - run: gem install bundler --version $BUNDLER_VERSION
25
+
26
+ - run:
27
+ name: install dependencies
28
+ command: |
29
+ bundle install --jobs=4 --retry=3 --path vendor/bundle
30
+
31
+ - save_cache:
32
+ paths:
33
+ - ./vendor/bundle
34
+ key: v1-dependencies-{{ checksum "Gemfile.lock" }}
35
+
36
+ # run tests!
37
+ - run:
38
+ name: run tests
39
+ command: |
40
+ mkdir /tmp/test-results
41
+ TEST_FILES="$(circleci tests glob "spec/**/*_spec.rb" | \
42
+ circleci tests split --split-by=timings)"
43
+
44
+ bundle exec rspec \
45
+ --format progress \
46
+ --format RspecJunitFormatter \
47
+ --out /tmp/test-results/rspec.xml \
48
+ --format progress \
49
+ $TEST_FILES
50
+
51
+ # collect reports
52
+ - store_test_results:
53
+ path: /tmp/test-results
54
+ - store_artifacts:
55
+ path: /tmp/test-results
56
+ destination: test-results
@@ -0,0 +1,15 @@
1
+ # EditorConfig is awesome: http://EditorConfig.org
2
+
3
+ # top-most EditorConfig file
4
+ root = true
5
+
6
+ # Unix-style newlines with a newline ending every file
7
+ [*]
8
+ end_of_line = lf
9
+ insert_final_newline = true
10
+ charset = utf-8
11
+
12
+ [*.{rb,yml,json,rake}]
13
+ indent_style = space
14
+ indent_size = 2
15
+ trim_trailing_whitespace = true
data/.rakeTasks CHANGED
@@ -4,4 +4,4 @@ You are allowed to:
4
4
  1. Remove rake task
5
5
  2. Add existing rake tasks
6
6
  To add existing rake tasks automatically delete this file and reload the project.
7
- --><RakeGroup description="" fullCmd="" taksId="rake"><RakeTask description="Build nxt_registry-0.1.0.gem into the pkg directory" fullCmd="build" taksId="build" /><RakeTask description="Remove any temporary products" fullCmd="clean" taksId="clean" /><RakeTask description="Remove any generated files" fullCmd="clobber" taksId="clobber" /><RakeTask description="Build and install nxt_registry-0.1.0.gem into system gems" fullCmd="install" taksId="install" /><RakeGroup description="" fullCmd="" taksId="install"><RakeTask description="Build and install nxt_registry-0.1.0.gem into system gems without network access" fullCmd="install:local" taksId="local" /></RakeGroup><RakeTask description="Create tag v0.1.0 and build and push nxt_registry-0.1.0.gem to TODO: Set to 'http://mygemserver.com'" fullCmd="release[remote]" taksId="release[remote]" /><RakeTask description="Run RSpec code examples" fullCmd="spec" taksId="spec" /><RakeTask description="" fullCmd="default" taksId="default" /><RakeTask description="" fullCmd="release" taksId="release" /><RakeGroup description="" fullCmd="" taksId="release"><RakeTask description="" fullCmd="release:guard_clean" taksId="guard_clean" /><RakeTask description="" fullCmd="release:rubygem_push" taksId="rubygem_push" /><RakeTask description="" fullCmd="release:source_control_push" taksId="source_control_push" /></RakeGroup></RakeGroup></Settings>
7
+ --><RakeGroup description="" fullCmd="" taksId="rake"><RakeTask description="Build nxt_registry-0.1.4.gem into the pkg directory" fullCmd="build" taksId="build" /><RakeTask description="Remove any temporary products" fullCmd="clean" taksId="clean" /><RakeTask description="Remove any generated files" fullCmd="clobber" taksId="clobber" /><RakeTask description="Build and install nxt_registry-0.1.4.gem into system gems" fullCmd="install" taksId="install" /><RakeGroup description="" fullCmd="" taksId="install"><RakeTask description="Build and install nxt_registry-0.1.4.gem into system gems without network access" fullCmd="install:local" taksId="local" /></RakeGroup><RakeTask description="Create tag v0.1.4 and build and push nxt_registry-0.1.4.gem to https://rubygems.org" fullCmd="release[remote]" taksId="release[remote]" /><RakeTask description="Run RSpec code examples" fullCmd="spec" taksId="spec" /><RakeTask description="" fullCmd="default" taksId="default" /><RakeTask description="" fullCmd="release" taksId="release" /><RakeGroup description="" fullCmd="" taksId="release"><RakeTask description="" fullCmd="release:guard_clean" taksId="guard_clean" /><RakeTask description="" fullCmd="release:rubygem_push" taksId="rubygem_push" /><RakeTask description="" fullCmd="release:source_control_push" taksId="source_control_push" /></RakeGroup></RakeGroup></Settings>
@@ -0,0 +1,33 @@
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
+
15
+ # v0.2.1 2020-08-14
16
+
17
+ ### Fixed
18
+
19
+ - Fixed Registry#fetch to raise key error in case of missing key
20
+
21
+ [Compare v0.2.0...v0.2.1](https://github.com/nxt-insurance/nxt_registry/compare/v0.2.0...v0.2.1)
22
+
23
+
24
+ # v0.2.0 2020-07-24
25
+
26
+ ### Added
27
+
28
+ - [internal] Added NxtRegistry::Singleton
29
+ - Added NxtRegistry::Singleton interface
30
+ - Make name optional and have object_id.to_s as default name
31
+ - Fix readme
32
+
33
+ [Compare v0.1.5...v0.2.0](https://github.com/nxt-insurance/nxt_registry/compare/v0.1.5...v0.2.0)
data/Gemfile CHANGED
@@ -2,3 +2,7 @@ source "https://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in nxt_registry.gemspec
4
4
  gemspec
5
+
6
+ group :test do
7
+ gem 'rspec_junit_formatter' # for CircleCI
8
+ end
@@ -1,46 +1,48 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- nxt_registry (0.1.3)
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.2.1)
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)
14
14
  tzinfo (~> 1.1)
15
- zeitwerk (~> 2.2)
16
- coderay (1.1.2)
17
- concurrent-ruby (1.1.5)
18
- diff-lcs (1.3)
19
- i18n (1.7.0)
15
+ zeitwerk (~> 2.2, >= 2.2.2)
16
+ coderay (1.1.3)
17
+ concurrent-ruby (1.1.7)
18
+ diff-lcs (1.4.4)
19
+ i18n (1.8.5)
20
20
  concurrent-ruby (~> 1.0)
21
- method_source (0.9.2)
22
- minitest (5.13.0)
23
- pry (0.12.2)
24
- coderay (~> 1.1.0)
25
- method_source (~> 0.9.0)
26
- rake (10.5.0)
21
+ method_source (1.0.0)
22
+ minitest (5.14.2)
23
+ pry (0.13.1)
24
+ coderay (~> 1.1)
25
+ method_source (~> 1.0)
26
+ rake (12.3.3)
27
27
  rspec (3.9.0)
28
28
  rspec-core (~> 3.9.0)
29
29
  rspec-expectations (~> 3.9.0)
30
30
  rspec-mocks (~> 3.9.0)
31
- rspec-core (3.9.0)
32
- rspec-support (~> 3.9.0)
33
- rspec-expectations (3.9.0)
31
+ rspec-core (3.9.2)
32
+ rspec-support (~> 3.9.3)
33
+ rspec-expectations (3.9.2)
34
34
  diff-lcs (>= 1.2.0, < 2.0)
35
35
  rspec-support (~> 3.9.0)
36
- rspec-mocks (3.9.0)
36
+ rspec-mocks (3.9.1)
37
37
  diff-lcs (>= 1.2.0, < 2.0)
38
38
  rspec-support (~> 3.9.0)
39
- rspec-support (3.9.0)
39
+ rspec-support (3.9.3)
40
+ rspec_junit_formatter (0.4.1)
41
+ rspec-core (>= 2, < 4, != 2.12.0)
40
42
  thread_safe (0.3.6)
41
- tzinfo (1.2.6)
43
+ tzinfo (1.2.7)
42
44
  thread_safe (~> 0.1)
43
- zeitwerk (2.2.2)
45
+ zeitwerk (2.4.0)
44
46
 
45
47
  PLATFORMS
46
48
  ruby
@@ -49,8 +51,9 @@ DEPENDENCIES
49
51
  bundler (~> 2.0)
50
52
  nxt_registry!
51
53
  pry
52
- rake (~> 10.0)
54
+ rake (~> 12)
53
55
  rspec (~> 3.0)
56
+ rspec_junit_formatter
54
57
 
55
58
  BUNDLED WITH
56
- 2.0.2
59
+ 2.1.4
data/README.md CHANGED
@@ -1,7 +1,9 @@
1
+ [![CircleCI](https://circleci.com/gh/nxt-insurance/nxt_registry.svg?style=svg)](https://circleci.com/gh/nxt-insurance/nxt_registry)
2
+
1
3
  # NxtRegistry
2
4
 
3
- NxtRegistry is a simple implementation of the container pattern. It allows you to register and resolve values in nested
4
- 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.
5
7
 
6
8
  ## Installation
7
9
 
@@ -21,80 +23,124 @@ Or install it yourself as:
21
23
 
22
24
  ## Usage
23
25
 
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:
31
+
24
32
  ```ruby
25
33
  class Example
26
34
  include NxtRegistry
27
35
 
28
- def passengers
29
- @passengers ||= begin
30
- registry :from do
31
- nested :to do
32
- nested :via, memoize: true, call: true, default: -> { [] } do
33
- attrs %i[train car plane horse] # restrict the attributes that can be registered
34
- resolver ->(value) { value } # do something with your registered value here
35
- transform_keys ->(key) { key.upcase } # transform keys
36
- end
37
- end
38
- end
39
- end
36
+ registry :languages do
37
+ register(:ruby, 'Stone')
38
+ register(:python, 'Snake')
39
+ register(:javascript, 'undefined')
40
40
  end
41
41
  end
42
42
 
43
43
  example = Example.new
44
- # Based on the naming of the registry and its nesting you are provided with a simple interface
45
- # that allows you to resolve and register values by name
46
-
47
- # Register an array with a value by calling the accessor with a key, value pair
48
- example.passengers.from(:a).to(:b).via(:train, ['Andy']) # => ['Andy']
49
-
50
- # In case you try to register the same key again you will get an error
51
- example.passengers.from(:a).to(:b).via(:train, ['Andy'])
52
- # => NxtRegistry::Errors::KeyAlreadyRegisteredError
53
- # (Key 'train' already registered in registry 'from.to.via')
54
- # NxtRegistry::Errors::KeyAlreadyRegisteredError inherits from KeyError
55
-
56
- # You can force values on the registry by using the bang method
57
- example.passengers.from(:a).to(:b).via!(:train, ['Andreas'])
44
+ example.registry(:languages).resolve(:ruby) # => 'Stone'
45
+ ```
58
46
 
59
- # Similarly you can try to resolve values softly
60
- # (meaning no KeyNotRegisteredError will be raised when nothing was registered)
61
- example.passengers.from(:a).to(:b).via!(:train)
62
- # Since there is a default defined for this registry, it does not make any sense
63
- # since there is always a value. But you get the point...
47
+ Alternatively you can also create instances of `NxtRegistry::Registry`
64
48
 
65
- # Resolve values by calling the accessor with the key only
66
- # In this case the default is returned because nothing was registered yet
67
- example.passengers.from(:a).to(:b).via(:hyperloop) # []
49
+ ```ruby
50
+ registry = NxtRegistry::Registry.new do
51
+ register(:andy, 'Andy')
52
+ register(:anthony, 'Anthony')
53
+ register(:aki, 'Aki')
54
+ end
68
55
 
69
- # Appending values to a default array
70
- example.passengers.from(:a).to(:b).via(:car) << 'Lütfi' # => ['Lütif']
71
- example.passengers.from(:a).to(:b).via(:plane) += %w[Nils Rapha]
72
- example.passengers.from(:a).to(:b).via(:plane) # => ['Nils', 'Rapha']
56
+ registry.resolve(:aki) # => 'Aki'
73
57
 
74
58
  ```
75
59
 
60
+ ## Class Level
61
+
62
+ You can register registries on the class level simply by extending your class with `NxtRegistry`
76
63
 
77
64
  ```ruby
78
65
  class OtherExample
79
66
  extend NxtRegistry
80
-
81
- # By passing a block to :registry you can directly register your values inline
82
- REGISTRY = registry(:errors) do
83
- # procs are called directly if not defined otherwise
67
+
68
+ registry(:errors) do
84
69
  register(KeyError, ->(error) { puts 'KeyError handler' } )
85
70
  register(ArgumentError, ->(error) { puts 'ArgumentError handler' } )
86
71
  end
72
+
73
+ registry(:country_codes) do
74
+ register(:germany, :de)
75
+ register(:england, :uk)
76
+ register(:france, :fr)
77
+ end
87
78
  end
88
79
 
89
- # Instead of using the name of the registry, you can also always call register and resolve on the
90
- # level where you want to register or resolve values. Equivalently to the named interface you can
91
- # use register! and resolve! to softly resolve or forcfully register values.
92
- OtherExample::REGISTRY.resolve(KeyError)
80
+ OtherExample.registry(:errors).resolve(KeyError)
93
81
  # KeyError handler
94
82
  # => nil
83
+ OtherExample.registry(:country_codes).resolve(:germany)
84
+ # => :de
85
+ ```
86
+ ### Readers
87
+
88
+ Access your defined registries with the `registry(:country_code)` method.
89
+
90
+ ### Nesting registries
95
91
 
92
+ You can also simply nest registries like so:
93
+
94
+ ```ruby
95
+ class Nested
96
+ extend NxtRegistry
97
+
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
108
+ end
109
+ end
110
+
111
+ Nested.registry(:developers).resolve(:frontend, :igor)
112
+ # => 'Igor'
96
113
  ```
97
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
+
98
144
  ### Restrict attributes to a certain set
99
145
 
100
146
  Use `attrs` to restrict which attributes can be registered on a specific level.
@@ -113,7 +159,7 @@ registry :example, default: ->(value) { 'default' }
113
159
 
114
160
  ### Blocks
115
161
 
116
- When you register a block value that can be called, tt will automatically be called when you resolve the value.
162
+ When you register a block value that can be called, it will automatically be called when you resolve the value.
117
163
  If that's not what you want, you can configure your registry (on each level) not to call blocks directly by defining `call false`
118
164
 
119
165
  ```ruby
@@ -124,7 +170,7 @@ end
124
170
 
125
171
  ### Memoize
126
172
 
127
- Values are memoized per default. Switch it off with `default false`
173
+ Values are memoized per default. Switch it off with `memoize: false`
128
174
 
129
175
  ```ruby
130
176
  registry :example, memoize: false do
@@ -141,7 +187,8 @@ registry.resolve(:one)
141
187
 
142
188
  ### Resolver
143
189
 
144
- You can register a resolver block if you want to lay hands on your values after they have been resolved.
190
+ You can register a resolver block if you want to lay hands on your values after they have been resolved.
191
+ A resolver can be anything that implements `:call` to which the value is passed.
145
192
 
146
193
  ```ruby
147
194
  registry :example do
@@ -155,9 +202,10 @@ registry.resolve(:one)
155
202
 
156
203
  ### Transform keys
157
204
 
158
- NxtRegistry uses a plain ruby hash to store values internally. Per default all keys used are transformed with `&:to_s`.
159
- 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`
160
- 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 }`
161
209
 
162
210
  ```ruby
163
211
  registry :example do
@@ -172,7 +220,7 @@ registry.resolve('BOMBSHELL')
172
220
  ### Customize registry errors
173
221
 
174
222
  You can also customize what kind of errors are being raised in case a of a key was not registered or was already registered.
175
- by providing values for `raise_key_already_registered_error` and `raise_key_not_registered_error`
223
+ by providing blocks or a handler responding to :call for `on_key_already_registered` and `on_key_already_registered`
176
224
 
177
225
  ## Development
178
226
 
@@ -3,16 +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
9
 
10
10
  module NxtRegistry
11
11
  def registry(name, **options, &config)
12
- 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
13
17
  end
14
18
 
15
19
  def recursive_registry(name, **options, &config)
16
- 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 ||= {}
17
31
  end
18
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
@@ -1,10 +1,10 @@
1
1
  module NxtRegistry
2
2
  class Registry
3
- def initialize(name, **options, &config)
3
+ def initialize(name = object_id.to_s, **options, &config)
4
4
  @name = name
5
5
  @parent = options[:parent]
6
6
  @is_leaf = true
7
- @namespace = parent ? name.to_s.prepend("#{parent.send(:namespace)}.") : name.to_s
7
+ @namespace = build_namespace
8
8
  @config = config
9
9
  @options = options
10
10
  @store = {}
@@ -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)
32
- raise ArgumentError, "Multiple nestings on the same level"
31
+ elsif default.is_a?(RegistryBuilder)
32
+ raise ArgumentError, 'Multiple nestings on the same level'
33
33
  else
34
- raise ArgumentError, "Default values cannot be defined on registries that nest others"
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
@@ -93,11 +123,11 @@ module NxtRegistry
93
123
  store.exclude?(transformed_key(key))
94
124
  end
95
125
 
96
- def fetch(key, **opts, &block)
97
- store.fetch(transformed_key(key), **opts, &block)
126
+ def fetch(key, *args, &block)
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
@@ -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
 
@@ -215,7 +244,6 @@ module NxtRegistry
215
244
  def define_accessors
216
245
  %w[default memoize call resolver transform_keys on_key_already_registered on_key_not_registered].each do |attribute|
217
246
  define_singleton_method attribute do |value = Blank.new, &block|
218
- # TODO: Allowing a block does not make sense for memoize and call?!
219
247
  value = block if block
220
248
 
221
249
  if value.is_a?(Blank)
@@ -237,9 +265,9 @@ module NxtRegistry
237
265
  attrs.keys.exclude?(transformed_key(key))
238
266
  end
239
267
 
240
- def resolve_default
268
+ def resolve_default(key)
241
269
  if call && default.respond_to?(:call)
242
- default.call
270
+ default.arity > 0 ? default.call(key) : default.call
243
271
  else
244
272
  default
245
273
  end
@@ -263,5 +291,19 @@ module NxtRegistry
263
291
  end
264
292
  end
265
293
  end
294
+
295
+ def initialize_copy(original)
296
+ super
297
+ @store = original.send(:store).deep_dup
298
+ @options = original.send(:options).deep_dup
299
+ end
300
+
301
+ def build_namespace
302
+ parent ? name.to_s.prepend("#{parent.send(:namespace)}.") : name.to_s
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
266
308
  end
267
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.1.3"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -35,7 +35,7 @@ Gem::Specification.new do |spec|
35
35
  spec.add_dependency "activesupport"
36
36
 
37
37
  spec.add_development_dependency "bundler", "~> 2.0"
38
- spec.add_development_dependency "rake", "~> 10.0"
38
+ spec.add_development_dependency "rake", "~> 12"
39
39
  spec.add_development_dependency "rspec", "~> 3.0"
40
40
  spec.add_development_dependency "pry"
41
41
  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.1.3
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-01-03 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
@@ -47,14 +47,14 @@ dependencies:
47
47
  requirements:
48
48
  - - "~>"
49
49
  - !ruby/object:Gem::Version
50
- version: '10.0'
50
+ version: '12'
51
51
  type: :development
52
52
  prerelease: false
53
53
  version_requirements: !ruby/object:Gem::Requirement
54
54
  requirements:
55
55
  - - "~>"
56
56
  - !ruby/object:Gem::Version
57
- version: '10.0'
57
+ version: '12'
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: rspec
60
60
  requirement: !ruby/object:Gem::Requirement
@@ -90,10 +90,13 @@ executables: []
90
90
  extensions: []
91
91
  extra_rdoc_files: []
92
92
  files:
93
+ - ".circleci/config.yml"
94
+ - ".editorconfig"
93
95
  - ".gitignore"
94
96
  - ".rakeTasks"
95
97
  - ".rspec"
96
98
  - ".travis.yml"
99
+ - CHANGELOG.md
97
100
  - Gemfile
98
101
  - Gemfile.lock
99
102
  - LICENSE.txt
@@ -105,9 +108,9 @@ files:
105
108
  - lib/nxt_registry/attribute.rb
106
109
  - lib/nxt_registry/blank.rb
107
110
  - lib/nxt_registry/errors.rb
108
- - lib/nxt_registry/nested_registry_builder.rb
109
111
  - lib/nxt_registry/recursive_registry.rb
110
112
  - lib/nxt_registry/registry.rb
113
+ - lib/nxt_registry/registry_builder.rb
111
114
  - lib/nxt_registry/version.rb
112
115
  - nxt_registry.gemspec
113
116
  homepage: https://github.com/nxt-insurance
@@ -132,7 +135,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
132
135
  - !ruby/object:Gem::Version
133
136
  version: '0'
134
137
  requirements: []
135
- rubygems_version: 3.0.6
138
+ rubygems_version: 3.0.3
136
139
  signing_key:
137
140
  specification_version: 4
138
141
  summary: nxt_registry is a simple implementation of the container pattern