event_bus 0.0.3 → 0.0.4
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.
- data/.rspec +2 -0
- data/.yardopts +1 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +3 -3
- data/README.md +21 -10
- data/lib/event_bus.rb +85 -43
- data/spec/lib/event_bus_spec.rb +76 -25
- metadata +6 -4
data/.rspec
ADDED
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--no-private
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
event_bus (0.0.
|
4
|
+
event_bus (0.0.3)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: http://rubygems.org/
|
8
8
|
specs:
|
9
9
|
diff-lcs (1.1.3)
|
10
10
|
multi_json (1.5.0)
|
11
|
-
rake (0.
|
11
|
+
rake (10.0.3)
|
12
12
|
rspec (2.12.0)
|
13
13
|
rspec-core (~> 2.12.0)
|
14
14
|
rspec-expectations (~> 2.12.0)
|
@@ -27,6 +27,6 @@ PLATFORMS
|
|
27
27
|
|
28
28
|
DEPENDENCIES
|
29
29
|
event_bus!
|
30
|
-
rake (~> 0.
|
30
|
+
rake (~> 10.0.1)
|
31
31
|
rspec (~> 2.12)
|
32
32
|
simplecov
|
data/README.md
CHANGED
@@ -3,6 +3,8 @@
|
|
3
3
|
A simple pubsub event bus for Ruby applications.
|
4
4
|
|
5
5
|
[](https://travis-ci.org/kevinrutherford/event_bus)
|
6
|
+
[](https://gemnasium.com/kevinrutherford/event_bus)
|
6
8
|
|
7
9
|
* <https://rubygems.org/gems/event_bus>
|
8
10
|
* <http://rubydoc.info/gems/event_bus/frames>
|
@@ -35,29 +37,38 @@ gem 'event_bus'
|
|
35
37
|
Subscribe to an event in your application's initialization code:
|
36
38
|
|
37
39
|
```ruby
|
38
|
-
EventBus.
|
40
|
+
EventBus.subscribe('order-placed', StatsRecorder.new, :order_placed)
|
39
41
|
```
|
40
42
|
|
41
|
-
|
43
|
+
```ruby
|
44
|
+
class StatsRecorder
|
45
|
+
def order_placed(details)
|
46
|
+
order = details[:order]
|
47
|
+
//...
|
48
|
+
end
|
49
|
+
end
|
50
|
+
```
|
51
|
+
|
52
|
+
Or subscribe a block:
|
42
53
|
|
43
54
|
```ruby
|
44
|
-
|
55
|
+
EventBus.subscribe('order-placed') do |details|
|
56
|
+
order = details[:order]
|
45
57
|
//...
|
46
|
-
EventBus.listen_for('order-placed', :order => current_order, :customer => current_user)
|
47
58
|
end
|
48
59
|
```
|
49
60
|
|
50
|
-
|
61
|
+
Fire the event whenever something significant happens in your application:
|
51
62
|
|
52
63
|
```ruby
|
53
|
-
class
|
54
|
-
|
55
|
-
|
56
|
-
//...
|
57
|
-
end
|
64
|
+
class PlaceOrder
|
65
|
+
//...
|
66
|
+
EventBus.announce('order-placed', :order => current_order, :customer => current_user)
|
58
67
|
end
|
59
68
|
```
|
60
69
|
|
70
|
+
See the specs for more detailed usage scenarios.
|
71
|
+
|
61
72
|
## Compatibility
|
62
73
|
|
63
74
|
Tested with Ruby 1.8.7, 1.9.x, JRuby, Rubinius.
|
data/lib/event_bus.rb
CHANGED
@@ -2,52 +2,75 @@ require 'singleton'
|
|
2
2
|
|
3
3
|
class EventBus
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
5
|
+
class << self
|
6
|
+
|
7
|
+
#
|
8
|
+
# Announce an event to any waiting listeners.
|
9
|
+
#
|
10
|
+
# The +event_name+ is added to the +details+ hash (with the key +:event_name+)
|
11
|
+
# before the event is passed on to listeners.
|
12
|
+
#
|
13
|
+
# @param event_name [String, Symbol] the name of your event
|
14
|
+
# @param details [Hash] the information you want to pass to the listeners
|
15
|
+
# @return the EventBus, ready to be called again.
|
16
|
+
#
|
17
|
+
def publish(event_name, details = {})
|
18
|
+
registrations.announce(event_name, details)
|
19
|
+
self
|
20
|
+
end
|
16
21
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
22
|
+
alias :announce :publish
|
23
|
+
alias :broadcast :publish
|
24
|
+
|
25
|
+
#
|
26
|
+
# Register a single listener.
|
27
|
+
#
|
28
|
+
# @param pattern [String, Regex] listen for any events whose name matches this pattern
|
29
|
+
# @param listener the object to be notified when a matching event occurs
|
30
|
+
# @param method_name [Symbol] the method to be called on +listener+ when a matching event occurs
|
31
|
+
# @return the EventBus, ready to be called again.
|
32
|
+
#
|
33
|
+
def subscribe(pattern, listener = nil, method_name = nil, &blk)
|
34
|
+
if listener
|
35
|
+
raise ArgumentError.new('You cannot give both a listener and a block') if block_given?
|
36
|
+
raise ArgumentError.new('You must supply a method name') unless method_name
|
37
|
+
registrations.add_method(pattern, listener, method_name)
|
38
|
+
else
|
39
|
+
raise ArgumentError.new('You must provide a listener or a block') unless block_given?
|
40
|
+
registrations.add_block(pattern, blk)
|
41
|
+
end
|
42
|
+
self
|
43
|
+
end
|
29
44
|
|
30
|
-
|
31
|
-
# Delete all current listener registrations
|
32
|
-
#
|
33
|
-
# @return the EventBus, ready to be called again.
|
34
|
-
#
|
35
|
-
def self.clear
|
36
|
-
Registrations.instance.clear
|
37
|
-
self
|
38
|
-
end
|
45
|
+
alias :listen_for :subscribe
|
39
46
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
47
|
+
#
|
48
|
+
# Delete all current listener registrations
|
49
|
+
#
|
50
|
+
# @return the EventBus, ready to be called again.
|
51
|
+
#
|
52
|
+
def clear
|
53
|
+
registrations.clear
|
54
|
+
self
|
55
|
+
end
|
56
|
+
|
57
|
+
#
|
58
|
+
# (experimental)
|
59
|
+
#
|
60
|
+
def register(listener)
|
61
|
+
listener.events_map.each do |pattern, method_name|
|
62
|
+
registrations.add(pattern, listener, method_name)
|
63
|
+
end
|
64
|
+
self
|
46
65
|
end
|
47
|
-
self
|
48
|
-
end
|
49
66
|
|
50
|
-
|
67
|
+
private
|
68
|
+
|
69
|
+
def registrations
|
70
|
+
Registrations.instance
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
51
74
|
|
52
75
|
class Registrations
|
53
76
|
include Singleton
|
@@ -57,8 +80,9 @@ class EventBus
|
|
57
80
|
end
|
58
81
|
|
59
82
|
def announce(event_name, details)
|
83
|
+
info = {:event_name => event_name}.merge(details)
|
60
84
|
@listeners.each do |listener|
|
61
|
-
listener.respond(event_name,
|
85
|
+
listener.respond(event_name, info)
|
62
86
|
end
|
63
87
|
end
|
64
88
|
|
@@ -66,10 +90,22 @@ class EventBus
|
|
66
90
|
@listeners = []
|
67
91
|
end
|
68
92
|
|
69
|
-
def
|
93
|
+
def add(pattern, listener, method_name, &blk)
|
94
|
+
if listener
|
95
|
+
add_method(pattern, listener, method_name)
|
96
|
+
else
|
97
|
+
add_block(pattern, blk)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def add_method(pattern, listener, method_name)
|
70
102
|
@listeners << Registration.new(pattern, listener, method_name)
|
71
103
|
end
|
72
104
|
|
105
|
+
def add_block(pattern, blk)
|
106
|
+
@listeners << BlockRegistration.new(pattern, blk)
|
107
|
+
end
|
108
|
+
|
73
109
|
private
|
74
110
|
|
75
111
|
Registration = Struct.new(:pattern, :listener, :method_name) do
|
@@ -78,6 +114,12 @@ class EventBus
|
|
78
114
|
end
|
79
115
|
end
|
80
116
|
|
117
|
+
BlockRegistration = Struct.new(:pattern, :block) do
|
118
|
+
def respond(event_name, details)
|
119
|
+
block.call(details) if pattern === event_name
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
81
123
|
end
|
82
124
|
|
83
125
|
end
|
data/spec/lib/event_bus_spec.rb
CHANGED
@@ -9,52 +9,103 @@ describe EventBus do
|
|
9
9
|
EventBus.clear
|
10
10
|
end
|
11
11
|
|
12
|
-
describe '.
|
12
|
+
describe '.publish' do
|
13
13
|
|
14
14
|
it 'returns itself, to facilitate cascades' do
|
15
|
-
EventBus.
|
15
|
+
EventBus.publish(event_name, {}).should == EventBus
|
16
16
|
end
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
EventBus.announce(event_name, {:a => 1, :b => 2})
|
23
|
-
end
|
18
|
+
it 'passes the event name in the details hash' do
|
19
|
+
EventBus.subscribe(event_name, listener, receiving_method)
|
20
|
+
listener.should_receive(receiving_method).with(:event_name => event_name)
|
21
|
+
EventBus.publish(event_name, {})
|
24
22
|
end
|
25
23
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
EventBus.announce(event_name, {:a => 1, :b => 2})
|
31
|
-
end
|
24
|
+
it 'allows the details hash to be omitted' do
|
25
|
+
EventBus.subscribe(event_name, listener, receiving_method)
|
26
|
+
listener.should_receive(receiving_method).with(:event_name => event_name)
|
27
|
+
EventBus.publish(event_name)
|
32
28
|
end
|
33
29
|
|
34
|
-
|
35
|
-
|
36
|
-
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '.subscribe' do
|
33
|
+
|
34
|
+
it 'returns itself, to facilitate cascades' do
|
35
|
+
EventBus.subscribe(event_name, listener, receiving_method).should == EventBus
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'accepts a string event name' do
|
39
|
+
it 'sends the event to a matching listener' do
|
40
|
+
EventBus.subscribe(event_name, listener, receiving_method)
|
41
|
+
listener.should_receive(receiving_method).with(:a => 1, :b => 2, :event_name => event_name)
|
42
|
+
EventBus.publish(event_name, :a => 1, :b => 2)
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'does not send the event to non-matching listeners' do
|
46
|
+
EventBus.subscribe('blah', listener, receiving_method)
|
37
47
|
listener.should_not_receive(receiving_method)
|
38
|
-
EventBus.
|
48
|
+
EventBus.publish(event_name, :a => 1, :b => 2, :event_name => event_name)
|
39
49
|
end
|
40
50
|
end
|
41
51
|
|
42
|
-
context '
|
43
|
-
it '
|
44
|
-
EventBus.
|
52
|
+
context 'accepts a regex event name' do
|
53
|
+
it 'sends the event to a matching listener' do
|
54
|
+
EventBus.subscribe(/123b/, listener, receiving_method)
|
55
|
+
listener.should_receive(receiving_method).with(:a => 1, :b => 2, :event_name => event_name)
|
56
|
+
EventBus.publish(event_name, :a => 1, :b => 2)
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'does not send the event to non-matching listeners' do
|
60
|
+
EventBus.subscribe(/123a/, listener, receiving_method)
|
45
61
|
listener.should_not_receive(receiving_method)
|
46
|
-
EventBus.
|
62
|
+
EventBus.publish(event_name, :a => 1, :b => 2, :event_name => event_name)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'can take a block or a receiver' do
|
67
|
+
it 'calls the block when the event matches' do
|
68
|
+
block_called = false
|
69
|
+
EventBus.subscribe(event_name) do |info|
|
70
|
+
block_called = true
|
71
|
+
info.should == {:a => 1, :b => 2, :event_name => event_name}
|
72
|
+
end
|
73
|
+
EventBus.publish(event_name, :a => 1, :b => 2)
|
74
|
+
block_called.should be_true
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'does not call the block when the event does not match' do
|
78
|
+
block_called = false
|
79
|
+
EventBus.subscribe('blah') {|_| block_called = true }
|
80
|
+
EventBus.publish(event_name, :a => 1, :b => 2)
|
81
|
+
block_called.should be_false
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context 'listener variant' do
|
86
|
+
it 'will not accept a block too' do
|
87
|
+
expect { EventBus.subscribe('blah', listener, receiving_method) {|info| }}.to raise_error(ArgumentError)
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'expects a method name' do
|
91
|
+
expect { EventBus.subscribe('blah', listener)}.to raise_error(ArgumentError)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
context 'block variant' do
|
96
|
+
it 'requires a block when no listener method is supplied' do
|
97
|
+
expect { EventBus.subscribe('blah')}.to raise_error(ArgumentError)
|
47
98
|
end
|
48
99
|
end
|
49
100
|
|
50
101
|
end
|
51
102
|
|
52
103
|
describe '.clear' do
|
53
|
-
it '
|
54
|
-
EventBus.
|
104
|
+
it 'removes all previous registrants' do
|
105
|
+
EventBus.subscribe(event_name, listener, receiving_method)
|
55
106
|
EventBus.clear
|
56
107
|
listener.should_not_receive(receiving_method)
|
57
|
-
EventBus.
|
108
|
+
EventBus.publish(event_name, {})
|
58
109
|
end
|
59
110
|
|
60
111
|
it 'returns itself, to facilitate cascades' do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: event_bus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-01-
|
12
|
+
date: 2013-01-27 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -18,7 +18,7 @@ dependencies:
|
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: 0.
|
21
|
+
version: 10.0.1
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -26,7 +26,7 @@ dependencies:
|
|
26
26
|
requirements:
|
27
27
|
- - ~>
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: 0.
|
29
|
+
version: 10.0.1
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
31
|
name: rspec
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,6 +66,8 @@ executables: []
|
|
66
66
|
extensions: []
|
67
67
|
extra_rdoc_files: []
|
68
68
|
files:
|
69
|
+
- .rspec
|
70
|
+
- .yardopts
|
69
71
|
- Gemfile
|
70
72
|
- Gemfile.lock
|
71
73
|
- README.md
|