racket-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
  SHA1:
3
- metadata.gz: d0ba35e3b8ae749a231ddfb8ebc8c1be932123fc
4
- data.tar.gz: dd77a4e59f964f4f23cddad580d3942ec5fc8096
3
+ metadata.gz: efdb66903525e8c25d4c9254fabeec1ba8171650
4
+ data.tar.gz: 30839afe56b0fd154c0cb1b99b4baa1e026055be
5
5
  SHA512:
6
- metadata.gz: 61e50e05a2981477850b0f431d8dcfd6c50440829f6b2dd89e78bfe2e3367b38930a0ca7d1404b8fb29d9062aa6bd45da1d728bd4b1b685961843707b4da7413
7
- data.tar.gz: 585da05068ae97d15b38247fdfe8c1625f97b18eddb8a4cdec8f3fd97cd310f4eccc06683a3dca703882189c0fb3d5449e597870213eee4a3649b4b18f69594f
6
+ metadata.gz: 6c1f7bf54264adcbb648b9c3c322a7cce347caea3d9c84d14b6a880c6636d16b6e11c398cb5eb3cc9ca980fede07c638e2c8518ddaaf66ec70975e97b4c94de6
7
+ data.tar.gz: 76634886929c092c1f44c412a2443c94f7fafe63e925ef20501e6bb501ec79cff0573fba5445faa2a348a5ecc05edfe6ecdc5cb3963ae2cd429d76f650c8beb3
data/README.md CHANGED
@@ -8,7 +8,7 @@ Racket Registry was originally intended for use in my home-made web framework, [
8
8
  The intention of the this library is to provide a very simple dependency injection container. Although not as useful in ruby as in less dynamic languages, I still think using a service container has its uses.
9
9
 
10
10
  ## How?
11
- Racket Registry allows you to register two kinds of procs, non-singletons and singletons. Registering also means that the container gets a new public method corresponding to the key used when registering the proc.
11
+ Racket Registry allows you to register two kinds of callbacks, non-singletons and singletons. Registering also means that the container gets a new public method corresponding to the key used when registering the callback.
12
12
 
13
13
  ```ruby
14
14
  require 'racket/registry'
@@ -83,5 +83,10 @@ registry.register(:foo, lambda { Object.new })
83
83
  registry.register(:foo) { Object.new }
84
84
  ```
85
85
 
86
+ ## "Unregistering" callbacks
87
+
88
+ If you want to "unregister" a specific callback, you can use `registry.forget(key)`. If you want to unregister all callbacks,
89
+ you can use `registry.forget_all`.
90
+
86
91
  ## Limitations
87
- When registering a proc, you must use a string/symbol as key. Since the registry is also defining a new public method, the key must not collide with any public method in Object or Racket::Registry.
92
+ When registering a callback, you must use a string/symbol as key. Since the registry is also defining a new public method, the key must represent a valid method name and also not collide with any public method in the registry.
@@ -20,79 +20,167 @@
20
20
  module Racket
21
21
  # Racket Registry namespace
22
22
  class Registry
23
- def initialize
24
- @resolved = {}
23
+ # Removes the callback specified by +key+ from the registry.
24
+ #
25
+ # @param [String|Symbol] key
26
+ # @return [nil]
27
+ def forget(key)
28
+ self.class.forget(obj: self, key: key)
25
29
  end
26
30
 
27
- # Registers a new proc in the registry. This will add a new method
31
+ # Removes all callbacks from the registry.
32
+ def forget_all
33
+ self.class.forget_all(obj: self)
34
+ end
35
+
36
+ # Registers a new callback in the registry. This will add a new method
28
37
  # matching +key+ to the registry that can be used both outside the
29
- # registry and when registering other procs dependant of the
30
- # current entry. Results from the proc will not be cached, meaning
31
- # that the proc may return a different object every time.
38
+ # registry and when registering other callbacks dependant of the
39
+ # current entry. Results from the callback will not be cached, meaning
40
+ # that the callback may return a different object every time.
32
41
  #
33
42
  # @param [String|Symbol] key
34
43
  # @param [Proc|nil] proc
35
44
  # @return [nil]
36
45
  def register(key, proc = nil, &block)
37
- key, proc, proc_args, =
38
- ClassMethods.validate_usable([key, self, proc, block, @resolved])
39
- singleton_class.instance_eval do
40
- define_method(key) { proc.call(*proc_args) }
41
- end && nil
46
+ self.class.register(
47
+ obj: self, key: key, proc: proc, block: block
48
+ )
42
49
  end
43
50
 
44
- # Registers a new proc in the registry. This will add a new method
51
+ # Registers a new callback in the registry. This will add a new method
45
52
  # matching +key+ to the registry that can be used both outside the
46
- # registry and when registering other procs dependant of the
47
- # current entry. Results from the proc will be cached, meaning
48
- # that the proc will return the same object every time.
53
+ # registry and when registering other callbacks dependant of the
54
+ # current entry. Results from the callnack will be cached, meaning
55
+ # that the callback will return the same object every time.
49
56
  #
50
57
  # @param [String|Symbol] key
51
58
  # @param [Proc|nil] proc
52
59
  # @return [nil]
53
60
  def register_singleton(key, proc = nil, &block)
54
- key, proc, proc_args, resolved =
55
- ClassMethods.validate_usable([key, self, proc, block, @resolved])
56
- singleton_class.instance_eval do
57
- define_method(key) do
58
- return resolved[key] if resolved.key?(key)
59
- resolved[key] = proc.call(*proc_args)
60
- end
61
- end && nil
61
+ self.class.register_singleton(
62
+ obj: self, key: key, proc: proc, block: block
63
+ )
62
64
  end
63
65
 
64
66
  alias singleton register_singleton
65
67
 
66
- # Racket Registry class methods
67
- module ClassMethods
68
- # Validates that the parameters sent to the registry is usable.
69
- #
70
- # @param [Array] args
71
- # @return [Array]
72
- def self.validate_usable(args)
73
- key, obj, proc, block, resolved = args
74
- key = validate_key(key, obj)
75
- proc = validate_proc(proc, block)
76
- [key, proc, proc.arity.zero? ? [] : [obj], resolved]
77
- end
78
-
79
- def self.validate_key(key, obj)
80
- sym = key.to_sym
81
- insp = key.inspect
82
- raise "Invalid key #{insp}" if
83
- Racket::Registry.public_methods.include?(sym) ||
84
- /^[a-z\_]{1}[\d\w\_]*$/ !~ sym
85
- raise "Key #{insp} already registered" if obj.respond_to?(key)
86
- sym
87
- end
88
-
89
- def self.validate_proc(proc, block)
90
- return proc if proc.respond_to?(:call)
91
- return block if block.respond_to?(:call)
92
- raise 'No proc/block given'
93
- end
94
-
95
- private_class_method :validate_key, :validate_proc
68
+ # Removes a callback from a registry.
69
+ #
70
+ # @param [Hash] options
71
+ # @return [nil]
72
+ def self.forget(options)
73
+ obj, methods, key = validate_existing(options)
74
+ raise KeyNotRegisteredError,
75
+ "Key #{key} is not registered" unless methods.include?(key)
76
+ obj.singleton_class.instance_eval do
77
+ @resolved.delete(key) if defined?(@resolved)
78
+ remove_method(key)
79
+ end && nil
80
+ end
81
+
82
+ # Removes all callbacks from a registry.
83
+ #
84
+ # @param [Hash] options
85
+ # @return [nil]
86
+ def self.forget_all(options)
87
+ obj, methods, = validate_existing(options)
88
+ obj.singleton_class.instance_eval do
89
+ @resolved.clear if defined?(@resolved)
90
+ methods.each { |meth| remove_method(meth) }
91
+ end && nil
92
+ end
93
+
94
+ # Registers a new callback to a registry. This will add a new method
95
+ # matching +key+ to the registry that can be used both outside the
96
+ # registry and when registering other callbacks dependant of the
97
+ # current entry. Results from the callback will not be cached, meaning
98
+ # that the callback may return a different object every time.
99
+ #
100
+ # @param [Hash] options
101
+ # @return [nil]
102
+ def self.register(options)
103
+ key, proc, proc_args, obj = validate_usable(options)
104
+ obj.define_singleton_method(key) do
105
+ proc.call(*proc_args)
106
+ end && nil
107
+ end
108
+
109
+ # Registers a new callback to a registry. This will add a new method
110
+ # matching +key+ to the registry that can be used both outside the
111
+ # registry and when registering other callbacks dependant of the
112
+ # current entry. Results from the callback will be cached, meaning
113
+ # that the callback will return the same object every time.
114
+ #
115
+ # @param [Hash] options
116
+ # @return [nil]
117
+ def self.register_singleton(options)
118
+ key, proc, proc_args, obj = validate_usable(options)
119
+ resolved = resolved(options[:obj])
120
+ obj.define_singleton_method(key) do
121
+ return resolved[key] if resolved.key?(key)
122
+ resolved[key] = proc.call(*proc_args)
123
+ end && nil
124
+ end
125
+
126
+ def self.resolved(obj)
127
+ obj.singleton_class.instance_eval { @resolved ||= {} }
128
+ end
129
+
130
+ def self.validate_existing(options)
131
+ result = [options[:obj]]
132
+ result << result.first.singleton_methods
133
+ key = options.fetch(:key, nil)
134
+ result << key.to_sym if key
135
+ result
136
+ end
137
+
138
+ def self.validate_key(key, obj)
139
+ sym = key.to_sym
140
+ insp = key.inspect
141
+ raise KeyAlreadyRegisteredError, "Key #{insp} already registered" if
142
+ obj.singleton_methods.include?(sym)
143
+ raise InvalidKeyError, "Invalid key #{insp}" if
144
+ obj.public_methods.include?(sym) ||
145
+ /^[a-z\_]{1}[\d\w\_]*$/ !~ sym
146
+ sym
147
+ end
148
+
149
+ def self.validate_callback(proc, block)
150
+ return proc if proc.respond_to?(:call)
151
+ return block if block.respond_to?(:call)
152
+ raise InvalidCallbackError, 'Invalid callback'
153
+ end
154
+
155
+ def self.validate_usable(options)
156
+ obj = options[:obj]
157
+ key = validate_key(options[:key], obj)
158
+ proc = validate_callback(options[:proc], options[:block])
159
+ [key, proc, proc.arity.zero? ? [] : [obj], obj]
160
+ end
161
+
162
+ private_class_method :resolved, :validate_callback,
163
+ :validate_existing, :validate_key,
164
+ :validate_usable
165
+
166
+ # Exception class used when a user tries to register an
167
+ # invalid callback.
168
+ class InvalidCallbackError < ArgumentError
169
+ end
170
+
171
+ # Exception class used when a user tries to register an
172
+ # invalid key.
173
+ class InvalidKeyError < ArgumentError
174
+ end
175
+
176
+ # Exception class used when a user tries to register a key
177
+ # that is already registered.
178
+ class KeyAlreadyRegisteredError < ArgumentError
179
+ end
180
+
181
+ # Exception class used when a user is requesting to forget
182
+ # a key that is not registered.
183
+ class KeyNotRegisteredError < ArgumentError
96
184
  end
97
185
  end
98
186
  end
@@ -67,24 +67,25 @@ describe 'Racket::Registry registration' do
67
67
 
68
68
  it 'should block invalid keys' do
69
69
  -> { registry.register('inspect') }
70
- .should.raise(RuntimeError)
70
+ .should.raise(Racket::Registry::InvalidKeyError)
71
71
  .message.should.equal('Invalid key "inspect"')
72
72
  end
73
73
 
74
74
  it 'should block already registered keys' do
75
75
  -> { registry.register('one', -> { Object.new }) }
76
- .should.raise(RuntimeError)
76
+ .should.raise(Racket::Registry::KeyAlreadyRegisteredError)
77
77
  .message.should.equal('Key "one" already registered')
78
78
  end
79
79
 
80
80
  it 'should block invalid block/procs' do
81
81
  -> { registry.register('invalid') }
82
- .should.raise(RuntimeError)
83
- .message.should.equal('No proc/block given')
82
+ .should.raise(Racket::Registry::InvalidCallbackError)
83
+ .message.should.equal('Invalid callback')
84
84
  end
85
85
  end
86
86
 
87
87
  describe 'Racket::Registry dependency handling' do
88
+ # A very simple class
88
89
  class Simple
89
90
  attr_reader :text
90
91
 
@@ -93,6 +94,7 @@ describe 'Racket::Registry dependency handling' do
93
94
  end
94
95
  end
95
96
 
97
+ # A somewhat complex class
96
98
  class NotSoSimple
97
99
  attr_reader :text, :simple_first, :simple_second
98
100
 
@@ -103,7 +105,8 @@ describe 'Racket::Registry dependency handling' do
103
105
  end
104
106
  end
105
107
 
106
- it 'should be able to resolve dependencies regardless of registration order' do
108
+ it 'should be able to resolve dependencies regardless of ' \
109
+ 'registration order' do
107
110
  registry = Racket::Registry.new
108
111
 
109
112
  foo = Simple.new('foo')
@@ -111,10 +114,10 @@ describe 'Racket::Registry dependency handling' do
111
114
 
112
115
  registry.singleton(
113
116
  :baz,
114
- lambda { |r| NotSoSimple.new('baz', r.foo, r.bar) }
117
+ ->(r) { NotSoSimple.new('baz', r.foo, r.bar) }
115
118
  )
116
- registry.singleton(:bar, lambda { |r| bar })
117
- registry.singleton(:foo, lambda { |r| foo })
119
+ registry.singleton(:bar, -> { bar })
120
+ registry.singleton(:foo, -> { foo })
118
121
 
119
122
  baz = registry.baz
120
123
  baz.simple_first.object_id.should.equal(foo.object_id)
@@ -123,3 +126,32 @@ describe 'Racket::Registry dependency handling' do
123
126
  registry.bar.object_id.should.equal(bar.object_id)
124
127
  end
125
128
  end
129
+
130
+ describe 'Racket::Registry entry removal' do
131
+ registry = Racket::Registry.new
132
+
133
+ it 'should be able to forget a single entry' do
134
+ obj = Object.new
135
+ registry.register(:foo) { obj }
136
+ registry.foo.object_id.should.equal(obj.object_id)
137
+ registry.forget(:foo)
138
+ -> { registry.foo }.should.raise(NoMethodError)
139
+ end
140
+
141
+ it 'should be able to forget all entries' do
142
+ obj = Object.new
143
+ registry.register(:foo) { obj }
144
+ registry.register(:bar) { obj }
145
+ registry.foo.object_id.should.equal(obj.object_id)
146
+ registry.bar.object_id.should.equal(obj.object_id)
147
+ registry.forget_all
148
+ -> { registry.foo }.should.raise(NoMethodError)
149
+ -> { registry.bar }.should.raise(NoMethodError)
150
+ end
151
+
152
+ it 'should fail to forget non-existing entries' do
153
+ -> { registry.forget(:baz) }
154
+ .should.raise(Racket::Registry::KeyNotRegisteredError)
155
+ .message.should.equal('Key baz is not registered')
156
+ end
157
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: racket-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
  - Lars Olsson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-06-22 00:00:00.000000000 Z
11
+ date: 2016-06-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bacon