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 ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --no-private
data/Gemfile CHANGED
@@ -3,7 +3,7 @@ gemspec
3
3
 
4
4
  group :test do
5
5
  gem 'rspec', '~> 2.12'
6
- gem 'rake', '~> 0.9.2'
6
+ gem 'rake', '~> 10.0.1'
7
7
  gem 'simplecov', :require => false
8
8
  end
9
9
 
data/Gemfile.lock CHANGED
@@ -1,14 +1,14 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- event_bus (0.0.2)
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.9.2.2)
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.9.2)
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.listen_for('order-placed', StatsRecorder.new, :order_placed)
40
+ EventBus.subscribe('order-placed', StatsRecorder.new, :order_placed)
39
41
  ```
40
42
 
41
- Fire the event whenever something significant happens in your application:
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
- class PlaceOrder
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
- Handle the event without coupling the publisher or subscriber:
61
+ Fire the event whenever something significant happens in your application:
51
62
 
52
63
  ```ruby
53
- class StatsRecorder
54
- def order_placed(details)
55
- order = details[:order]
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
- # Announce an event to any waiting listeners.
7
- #
8
- # @param event_name [String, Symbol] the name of your event
9
- # @param details [Hash] the information you want to pass to the listeners
10
- # @return the EventBus, ready to be called again.
11
- #
12
- def self.announce(event_name, details)
13
- Registrations.instance.announce(event_name, details)
14
- self
15
- end
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
- # Register a single listener.
19
- #
20
- # @param pattern [String, Regex] listen for any events whose name matches this pattern
21
- # @param listener the object to be notified when a matching event occurs
22
- # @param method_name [Symbol] the method to be called on listener when a matching event occurs
23
- # @return the EventBus, ready to be called again.
24
- #
25
- def self.listen_for(pattern, listener, method_name)
26
- Registrations.instance.register(pattern, listener, method_name)
27
- self
28
- end
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
- # (experimental)
42
- #
43
- def self.register(listener)
44
- listener.events_map.each do |pattern, method_name|
45
- Registrations.instance.register(pattern, listener, method_name)
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
- private
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, details)
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 register(pattern, listener, method_name)
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
@@ -9,52 +9,103 @@ describe EventBus do
9
9
  EventBus.clear
10
10
  end
11
11
 
12
- describe '.announce' do
12
+ describe '.publish' do
13
13
 
14
14
  it 'returns itself, to facilitate cascades' do
15
- EventBus.clear.should == EventBus
15
+ EventBus.publish(event_name, {}).should == EventBus
16
16
  end
17
17
 
18
- context 'when the listener is specific about the event name' do
19
- it 'sends the event to the listener' do
20
- EventBus.listen_for(event_name, listener, receiving_method)
21
- listener.should_receive(receiving_method).with({:a => 1, :b => 2})
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
- context 'when the listener uses a regex that matches' do
27
- it 'sends the event to the listener' do
28
- EventBus.listen_for(/123b/, listener, receiving_method)
29
- listener.should_receive(receiving_method).with({:a => 1, :b => 2})
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
- context 'when the listener listens for a different event' do
35
- it 'does not send the event to the listener' do
36
- EventBus.listen_for('blah', listener, receiving_method)
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.announce(event_name, {:a => 1, :b => 2})
48
+ EventBus.publish(event_name, :a => 1, :b => 2, :event_name => event_name)
39
49
  end
40
50
  end
41
51
 
42
- context 'when the listener listens for a non-matching regex' do
43
- it 'does not send the event to the listener' do
44
- EventBus.listen_for(/123a/, listener, receiving_method)
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.announce(event_name, {:a => 1, :b => 2})
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 'sends no event to previous registrants' do
54
- EventBus.listen_for(event_name, listener, receiving_method)
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.announce(event_name, {})
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.3
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-24 00:00:00.000000000 Z
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.9.2
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.9.2
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