signals 0.0.2 → 1.0.0

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
  SHA1:
3
- metadata.gz: 682db5800cf5ba91ba8694e672f9ba94cc766e27
4
- data.tar.gz: 360251fd4a443e0ddac0b738af93e4a05e713026
3
+ metadata.gz: d0a17dcf963e613b1958719ee6335e765e1f4233
4
+ data.tar.gz: f322c5f49706eb819a44e39a8bb54211bf7fc49b
5
5
  SHA512:
6
- metadata.gz: 2bfa9e3d66d07c05840b374089148a69a124fce7fbfd4760ccf896fd331a033751b81a87ecb174d47bfbadba11a95411abdb094301ff53deb07b471d5cbd2fe2
7
- data.tar.gz: 684f968ef7cdfd6be8c9ca7a28e0a49f5e67a7a042a3ad35d703f675809d6b538968017089b3c2a7fa006aa540814888b963a8ab322e7b67a5f11248451b7bb2
6
+ metadata.gz: c6317c3d341b4fd50be0eaf0ef67e5ce8bbab4e1bb99ab60c4a4fa21dbe27d3d3bf6efbc57831b0ca82bb31572dd7be9b020d4ebcc8a3524fe403c4b425de9e0
7
+ data.tar.gz: e20efc2de3708bbf8e53ba7a574dd353799dfd0d58d51787f16e895844287c4f94000ecbbe61a4c142bccb4180841d608a2e2e724804f52ceabef8bf0778eccb
data/.gitignore CHANGED
@@ -15,3 +15,5 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
+ *.sublime-workspace
19
+ *.sublime-project
data/README.md CHANGED
@@ -17,30 +17,43 @@ require 'signals'
17
17
 
18
18
  class Coach
19
19
  include Signals::Publisher
20
-
21
- def run_play
22
- broadcast(:v_formation, self)
23
- end
24
20
  end
25
21
 
26
22
  class Player
23
+ include Signals::Subscriber
24
+
25
+ listen_for :v_formation => :run
26
+ listen_for [:hat_trick, :v_formation] => :audible
27
+ listen_for :stop => [:look, :run]
28
+ listen_for :stop => :audible
29
+
27
30
  def initialize(name)
28
31
  @name = name
29
32
  end
30
33
 
31
- def v_formation(coach)
32
- puts "#{@name} is in position"
34
+ def run(coach)
35
+ puts "#{@name} is running"
36
+ end
37
+
38
+ def audible(coach)
39
+ puts "#{@name} is calling an audible"
40
+ end
41
+
42
+ def look(coach)
43
+ puts "#{@name} is looking"
33
44
  end
34
45
  end
35
46
 
36
- coach = Coach.new
47
+ coach = Coach.new
37
48
  forward = Player.new('John')
38
- center = Player.new('Jeff')
49
+ center = Player.new('Jeff')
39
50
 
40
51
  coach.subscribe(forward)
41
52
  coach.subscribe(center)
42
53
 
43
- coach.run_play
54
+ coach.on(:stop) do |c|
55
+ puts "I'm telling you to stop"
56
+ end
44
57
  ```
45
58
 
46
59
  ## Contributing
@@ -10,7 +10,7 @@ module Signals
10
10
  @event = event
11
11
  end
12
12
 
13
- def execute(event, *args)
13
+ def execute_event(event, *args)
14
14
  if self.event == event
15
15
  self.listener.call(*args)
16
16
  end
@@ -1,34 +1,45 @@
1
1
  module Signals
2
2
 
3
3
  module Publisher
4
- # Broadcasts an event to all of the subscribed listeners
5
- # @return [void]
6
- def broadcast(event, *args)
7
- listeners.each do |listener|
8
- listener.execute(event, *args)
9
- end
10
- nil
11
- end
12
4
 
13
- # Creates a one off listener that will respond to the event provided only
14
- # @param [Object] event the event that is triggered
15
- # @return [void]
16
- def on(event, &block)
17
- listeners.add(BlockListener.new(event, &block))
18
- nil
5
+ def self.included(base)
6
+ base.extend(ClassMethods)
7
+ base.send(:include, InstanceMethods)
19
8
  end
20
9
 
21
- # Subscribe a listener to the publisher
22
- # @return [void]
23
- def subscribe(listener)
24
- listeners.add(Listener.new(listener))
25
- nil
10
+ module ClassMethods
26
11
  end
27
12
 
28
- # All of the listeners subscribed to a publisher
29
- # @return [Set] a unique set of listeners
30
- def listeners
31
- @listeners ||= Set.new
13
+ module InstanceMethods
14
+ # Broadcasts an event to all of the subscribed listeners
15
+ # @return [void]
16
+ def broadcast(event, *args)
17
+ listeners.each do |listener|
18
+ listener.execute_event(event, *args)
19
+ end
20
+ nil
21
+ end
22
+
23
+ # Creates a one off listener that will respond to the event provided only
24
+ # @param [Object] event the event that is triggered
25
+ # @return [void]
26
+ def on(event, &block)
27
+ listeners.add(BlockListener.new(event, &block))
28
+ nil
29
+ end
30
+
31
+ # Subscribe a listener to the publisher
32
+ # @return [void]
33
+ def subscribe(listener)
34
+ listeners.add(listener)
35
+ nil
36
+ end
37
+
38
+ # All of the listeners subscribed to a publisher
39
+ # @return [Set] a unique set of listeners
40
+ def listeners
41
+ @listeners ||= Set.new
42
+ end
32
43
  end
33
44
  end
34
45
 
@@ -0,0 +1,125 @@
1
+ module Signals
2
+
3
+ module Subscriber
4
+
5
+ def self.included(base)
6
+ base.extend(ClassMethods)
7
+ base.send(:include, InstanceMethods)
8
+ end
9
+
10
+ module ClassMethods
11
+ # Register the class to listen for specific events and react accordingly.
12
+ # Any combination can be used. Listen for only accepts a hash as the
13
+ # parameter.
14
+ #
15
+ # == Example
16
+ #
17
+ # class Something
18
+ # include Signals::Subscriber
19
+ #
20
+ # listen_for :one => :action
21
+ # listen_for :one => [:action, :another]
22
+ # listen_for :one => [:and_another]
23
+ # listen_for [:one, :two] => :action
24
+ # listen_for [:one, :two] => [:action]
25
+ # listen_for [:one] => [:and_another]
26
+ # end
27
+ #
28
+ # @param [Hash] params
29
+ # @return [void]
30
+ def listen_for(params={})
31
+ params.each do |k, v|
32
+ if k.is_a?(Array)
33
+ k.each { |e| add_event(e, v) }
34
+ else
35
+ add_event(k, v)
36
+ end
37
+ end
38
+ nil
39
+ end
40
+
41
+ # @param [Symbol] e the event
42
+ # @param [Array|Symbol] actions the actions to be taken
43
+ def add_event(e, actions)
44
+ event(e).concat(actions.is_a?(Array) ? actions : [actions])
45
+ end
46
+
47
+ # @return [Hash]
48
+ def events
49
+ @@events ||= Hash.new
50
+ end
51
+
52
+ private
53
+
54
+ # @param [Symbol] key
55
+ # @return [Array]
56
+ def event(key)
57
+ events[key] ||= Array.new
58
+ end
59
+ end
60
+
61
+ module InstanceMethods
62
+ def execute_event(event, *args)
63
+ if event_enabled?(event)
64
+ actions_for(event).each do |action|
65
+ self.send(action, *args) if self.respond_to?(action)
66
+ end
67
+ end
68
+ end
69
+
70
+ # Disables an event temporarily
71
+ # @param [Symbol] event
72
+ # @return [void]
73
+ def disable_event(event)
74
+ disabled_events.add(event)
75
+ nil
76
+ end
77
+
78
+ # Enables an event that was disabled
79
+ # @param [Symbol] event
80
+ # @return [void]
81
+ def enable_event(event)
82
+ disabled_events.delete(event)
83
+ nil
84
+ end
85
+
86
+ # Checks to see if the event is disabled
87
+ # @param [Symbol] event
88
+ # @return [Boolean]
89
+ def event_disabled?(event)
90
+ disabled_events.include?(event)
91
+ end
92
+
93
+ # Checks to see if the event is enabled
94
+ # @param [Symbol] event
95
+ # @return [Boolean]
96
+ def event_enabled?(event)
97
+ !event_disabled?(event)
98
+ end
99
+
100
+ # Checks to see if the event is present
101
+ # @param [Symbol] event
102
+ # @return [Boolean]
103
+ def event?(event)
104
+ events.include?(event)
105
+ end
106
+
107
+ def actions_for(event)
108
+ self.events[event] || Array.new
109
+ end
110
+
111
+ # The set of disabled events
112
+ # @return [Set] a set of disabled events
113
+ def disabled_events
114
+ @disabled_events ||= Set.new
115
+ end
116
+
117
+ # The hash of events that the subscriber is listening for
118
+ # @return [Hash]
119
+ def events
120
+ self.class.events.freeze
121
+ end
122
+ end
123
+ end
124
+
125
+ end
@@ -1,3 +1,3 @@
1
1
  module Signals
2
- VERSION = "0.0.2"
2
+ VERSION = "1.0.0"
3
3
  end
data/lib/signals.rb CHANGED
@@ -3,6 +3,6 @@ end
3
3
 
4
4
  require 'set'
5
5
  require 'signals/version'
6
- require 'signals/listener'
7
6
  require 'signals/block_listener'
8
7
  require 'signals/publisher'
8
+ require 'signals/subscriber'
@@ -2,12 +2,12 @@ require 'spec_helper'
2
2
 
3
3
  describe Signals::BlockListener do
4
4
 
5
- describe '#execute' do
5
+ describe '#execute_event' do
6
6
  it 'should execute the event it was registered for' do
7
7
  block = Signals::BlockListener.new(:testing)
8
8
  block.stub(listener: double('lambda', call: true))
9
9
 
10
- block.execute(:testing)
10
+ block.execute_event(:testing)
11
11
 
12
12
  block.listener.should have_received(:call).once
13
13
  end
@@ -16,7 +16,7 @@ describe Signals::BlockListener do
16
16
  block = Signals::BlockListener.new(:testing)
17
17
  block.stub(listener: double('lambda', call: true))
18
18
 
19
- block.execute(:another)
19
+ block.execute_event(:another)
20
20
 
21
21
  block.listener.should_not have_received(:call)
22
22
  end
@@ -25,7 +25,7 @@ describe Signals::BlockListener do
25
25
  block = Signals::BlockListener.new(:testing)
26
26
  block.stub(listener: double('lambda', call: true))
27
27
 
28
- block.execute(:testing, 1, 2)
28
+ block.execute_event(:testing, 1, 2)
29
29
 
30
30
  block.listener.should have_received(:call).with(1,2).once
31
31
  end
@@ -5,42 +5,49 @@ describe Signals::Publisher do
5
5
  include Signals::Publisher
6
6
  end
7
7
 
8
- class SimpleListener
9
- end
10
-
11
- let(:publisher) { DummyPublisher.new }
12
-
13
8
  describe '#broadcast' do
14
- it 'should broadcast an event' do
15
- listener = double('AListener', execute: true)
16
- publisher.stub(listeners: Set.new([listener]))
9
+ it 'should broadcast an event to subscribers' do
10
+ publisher = DummyPublisher.new
11
+ listener = double('Listener', execute_event: true)
12
+ listeners = [listener]
13
+ publisher.stub(listeners: listeners)
17
14
 
18
15
  publisher.broadcast(:event, 1, 2)
19
16
 
20
- listener.should have_received(:execute).with(:event, 1, 2)
17
+ listener.should have_received(:execute_event).with(:event, 1, 2)
21
18
  end
22
19
  end
23
20
 
24
- describe '#subscribe' do
25
- it 'should subscribe a listener' do
26
- expect {
27
- publisher.subscribe(SimpleListener.new)
28
- }.to_not raise_error
21
+ describe '#on' do
22
+ it 'should should be successful' do
23
+ publisher = DummyPublisher.new
24
+ listeners = double('Set', add: true)
25
+ publisher.stub(listeners: listeners)
26
+
27
+ publisher.on(:event) do
28
+ true
29
+ end
30
+
31
+ listeners.should have_received(:add).once
29
32
  end
30
33
  end
31
34
 
32
- describe '#on' do
33
- it 'should subscribe a block listener' do
34
- publisher.stub(listeners: double('Set', add: true))
35
+ describe '#subscribe' do
36
+ it 'should subscribe a subscriber' do
37
+ publisher = DummyPublisher.new
38
+ listeners = double('Set', add: true)
39
+ listener = double('Listener')
40
+ publisher.stub(listeners: listeners)
35
41
 
36
- publisher.on(:event) { true }
42
+ publisher.subscribe(listener)
37
43
 
38
- publisher.listeners.should have_received(:add).once
44
+ listeners.should have_received(:add).with(listener).once
39
45
  end
40
46
  end
41
47
 
42
48
  describe '#listeners' do
43
- subject { publisher.listeners }
49
+ subject { DummyPublisher.new.listeners }
44
50
  it { should be_a(Set) }
45
51
  end
52
+
46
53
  end
@@ -0,0 +1,262 @@
1
+ require 'spec_helper'
2
+
3
+ describe Signals::Subscriber do
4
+ class DummySubscriber
5
+ include Signals::Subscriber
6
+
7
+ listen_for :event => :action_1
8
+ listen_for :complex => [:action_2, :action_3]
9
+ listen_for [:event, :complex] => :action_4
10
+ listen_for [:event, :complex] => [:action_5, :action_6]
11
+ end
12
+
13
+ describe '#execute_event' do
14
+ context 'when the event is disabled' do
15
+ it 'should not execute the actions' do
16
+ subscriber = DummySubscriber.new
17
+ subscriber.stub(event_enabled?: false, action_1: true)
18
+
19
+ subscriber.execute_event(:event)
20
+
21
+ subscriber.should_not have_received(:action_1)
22
+ end
23
+ end
24
+
25
+ context 'when the event is enabled' do
26
+ it 'should execute the actions' do
27
+ subscriber = DummySubscriber.new
28
+ subscriber.stub(event_enabled?: true, action_1: true)
29
+
30
+ subscriber.execute_event(:event)
31
+
32
+ subscriber.should have_received(:action_1).once
33
+ end
34
+ end
35
+ end
36
+
37
+
38
+ describe '#disable_event' do
39
+ it 'should disable an event' do
40
+ subscriber = DummySubscriber.new
41
+ events = double('Events', add: true)
42
+ subscriber.stub(disabled_events: events)
43
+
44
+ subscriber.disable_event(:event)
45
+
46
+ events.should have_received(:add).with(:event).once
47
+ end
48
+ end
49
+
50
+
51
+ describe '#enable_event' do
52
+ it 'should enable an event' do
53
+ subscriber = DummySubscriber.new
54
+ events = double('Events', delete: true)
55
+ subscriber.stub(disabled_events: events)
56
+
57
+ subscriber.enable_event(:event)
58
+
59
+ events.should have_received(:delete).with(:event).once
60
+ end
61
+ end
62
+
63
+
64
+ describe '#event_disabled?' do
65
+ context 'when an event is disabled' do
66
+ it 'should return true' do
67
+ subscriber = DummySubscriber.new
68
+ set = Set.new([:event])
69
+ subscriber.stub(disabled_events: set)
70
+
71
+ subscriber.event_disabled?(:event).should be_true
72
+ end
73
+ end
74
+
75
+ context 'when an event is enabled' do
76
+ it 'should return false' do
77
+ subscriber = DummySubscriber.new
78
+ set = Set.new([])
79
+ subscriber.stub(disabled_events: set)
80
+
81
+ subscriber.event_disabled?(:event).should be_false
82
+ end
83
+ end
84
+ end
85
+
86
+
87
+ describe '#event_enabled?' do
88
+ context 'when an event is disabled' do
89
+ it 'should return false' do
90
+ subscriber = DummySubscriber.new
91
+ set = Set.new([:event])
92
+ subscriber.stub(disabled_events: set)
93
+
94
+ subscriber.event_enabled?(:event).should be_false
95
+ end
96
+ end
97
+
98
+ context 'when an event is enabled' do
99
+ it 'should return true' do
100
+ subscriber = DummySubscriber.new
101
+ set = Set.new([])
102
+ subscriber.stub(disabled_events: set)
103
+
104
+ subscriber.event_enabled?(:event).should be_true
105
+ end
106
+ end
107
+ end
108
+
109
+
110
+ describe '#event?' do
111
+ context 'when the event is on the subscriber' do
112
+ it 'should return true' do
113
+ subscriber = DummySubscriber.new
114
+ subscriber.event?(:event).should be_true
115
+ end
116
+ end
117
+
118
+ context 'when the event is not on the subscriber' do
119
+ it 'should return false' do
120
+ subscriber = DummySubscriber.new
121
+ subscriber.event?(:not_here).should be_false
122
+ end
123
+ end
124
+ end
125
+
126
+
127
+ describe '#actions_for' do
128
+ context 'when the event is on the subscriber' do
129
+ it 'should return return its actions' do
130
+ subscriber = DummySubscriber.new
131
+ subscriber.actions_for(:event).should eq([:action_1, :action_4, :action_5, :action_6])
132
+ end
133
+ end
134
+
135
+ context 'when the event is not on the subscriber' do
136
+ it 'should return false' do
137
+ subscriber = DummySubscriber.new
138
+ subscriber.actions_for(:not_here).should eq([])
139
+ end
140
+ end
141
+ end
142
+
143
+
144
+ describe '#disabled_events' do
145
+ context 'when no events are disabled' do
146
+ it 'should be an empty set' do
147
+ subscriber = DummySubscriber.new
148
+ subscriber.disabled_events.should be_empty
149
+ end
150
+ end
151
+
152
+ context 'when an event is disabled' do
153
+ it 'should not be empty' do
154
+ subscriber = DummySubscriber.new
155
+ subscriber.disable_event(:event)
156
+ subscriber.disabled_events.should_not be_empty
157
+ end
158
+ end
159
+ end
160
+
161
+
162
+ describe '#events' do
163
+ it 'should not be empty' do
164
+ subscriber = DummySubscriber.new
165
+ subscriber.events.should_not be_empty
166
+ end
167
+ end
168
+
169
+
170
+ describe '.listen_for' do
171
+ class SubscriberListenTest
172
+ include Signals::Subscriber
173
+ end
174
+ let(:klass) { SubscriberListenTest }
175
+ context 'when the event is a symbol' do
176
+ context 'when the action is a symbol' do
177
+ it 'should register the action for the event' do
178
+ klass.stub(add_event: true)
179
+
180
+ klass.listen_for(:event_1 => :action_1)
181
+
182
+ klass.should have_received(:add_event).with(:event_1, :action_1)
183
+ end
184
+ end
185
+
186
+ context 'when the action is an array of symbols' do
187
+ it 'should register the actions for the event' do
188
+ klass.stub(add_event: true)
189
+
190
+ klass.listen_for(:event_1 => [:action_2, :action_3])
191
+
192
+ klass.should have_received(:add_event).with(:event_1, [:action_2, :action_3])
193
+ end
194
+ end
195
+ end
196
+
197
+ context 'when the event is an array of symbols' do
198
+ context 'when the action is a symbol' do
199
+ it 'should register the action for the events' do
200
+ klass.stub(add_event: true)
201
+
202
+ klass.listen_for([:event_2, :event_3] => :action_1)
203
+
204
+ klass.should have_received(:add_event).twice
205
+ end
206
+ end
207
+ context 'when the action is an array of symbols' do
208
+ it 'should register the actions for the events' do
209
+ klass.stub(add_event: true)
210
+
211
+ klass.listen_for([:event_2, :event_3] => [:action_1, :action_2])
212
+
213
+ klass.should have_received(:add_event).twice
214
+ end
215
+ end
216
+ end
217
+ end
218
+
219
+
220
+ describe '.add_event' do
221
+ class SubscriberAddEvent
222
+ include Signals::Subscriber
223
+ end
224
+ let(:klass) { SubscriberAddEvent }
225
+
226
+ context 'when the actions is an array of symbols' do
227
+ it 'should be successful' do
228
+ hash = double('Hash', concat: true)
229
+ klass.stub(event: hash)
230
+
231
+ klass.add_event(:event_1, [:action_1, :action_2])
232
+
233
+ klass.should have_received(:event).with(:event_1)
234
+ end
235
+ end
236
+ context 'when the action is a symbol' do
237
+ it 'should be successful' do
238
+ hash = double('Hash', concat: true)
239
+ klass.stub(event: hash)
240
+
241
+ klass.add_event(:event_1, :action_3)
242
+
243
+ klass.should have_received(:event).with(:event_1)
244
+ end
245
+ end
246
+ end
247
+
248
+
249
+ describe '.events' do
250
+ subject { DummySubscriber.events }
251
+ it { should be_a(Hash) }
252
+ end
253
+
254
+
255
+ describe '.event' do
256
+ it 'should raise an exception' do
257
+ expect {
258
+ DummySubscriber.event(1)
259
+ }.to raise_error
260
+ end
261
+ end
262
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: signals
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthew Johnston
@@ -69,13 +69,13 @@ files:
69
69
  - Rakefile
70
70
  - lib/signals.rb
71
71
  - lib/signals/block_listener.rb
72
- - lib/signals/listener.rb
73
72
  - lib/signals/publisher.rb
73
+ - lib/signals/subscriber.rb
74
74
  - lib/signals/version.rb
75
75
  - signals.gemspec
76
76
  - spec/signals/block_listener_spec.rb
77
- - spec/signals/listener_spec.rb
78
77
  - spec/signals/publisher_spec.rb
78
+ - spec/signals/subscriber_spec.rb
79
79
  - spec/spec_helper.rb
80
80
  homepage: https://github.com/warmwaffles/signals
81
81
  licenses:
@@ -103,6 +103,6 @@ specification_version: 4
103
103
  summary: A lightweight publish / subscribe library
104
104
  test_files:
105
105
  - spec/signals/block_listener_spec.rb
106
- - spec/signals/listener_spec.rb
107
106
  - spec/signals/publisher_spec.rb
107
+ - spec/signals/subscriber_spec.rb
108
108
  - spec/spec_helper.rb
@@ -1,21 +0,0 @@
1
- module Signals
2
-
3
- class Listener
4
- attr_reader :listener
5
-
6
- # @param [Object] listener the listener you want to use
7
- def initialize(listener)
8
- @listener = listener
9
- end
10
-
11
- # @param [Object] event
12
- # @return [void]
13
- def execute(event, *args)
14
- if @listener.respond_to?(event)
15
- @listener.send(event, *args)
16
- end
17
- nil
18
- end
19
- end
20
-
21
- end
@@ -1,31 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Signals::Listener do
4
-
5
- describe '#execute' do
6
- it 'should execute an existing method with no params' do
7
- simple = double('SimpleListener', testing: true)
8
- listener = Signals::Listener.new(simple)
9
-
10
- listener.execute(:testing)
11
-
12
- listener.listener.should have_received(:testing).once
13
- end
14
-
15
- it 'should execute an existing method with params' do
16
- simple = double('SimpleListener', testing: true)
17
- listener = Signals::Listener.new(simple)
18
-
19
- listener.execute(:testing, 1, 2)
20
-
21
- listener.listener.should have_received(:testing).with(1, 2).once
22
- end
23
-
24
- it 'should not raise an error when the method does not exist' do
25
- simple = double('SimpleListener')
26
- listener = Signals::Listener.new(simple)
27
-
28
- expect { listener.execute(:testing) }.to_not raise_error
29
- end
30
- end
31
- end