event_bus 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Build Status](https://travis-ci.org/kevinrutherford/event_bus.png)](https://travis-ci.org/kevinrutherford/event_bus)
|
6
|
+
[![Dependency
|
7
|
+
Status](https://gemnasium.com/kevinrutherford/event_bus.png)](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
|