wisper 1.0.0 → 1.0.1
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/README.md +131 -29
- data/lib/wisper.rb +7 -1
- data/lib/wisper/global_listeners.rb +28 -0
- data/lib/wisper/registration/object.rb +14 -3
- data/lib/wisper/registration/object/async_listener.rb +23 -0
- data/lib/wisper/rspec/stub_wisper_publisher.rb +15 -0
- data/lib/wisper/version.rb +1 -1
- data/spec/lib/async_spec.rb +34 -0
- data/spec/lib/global_subscribers_spec.rb +28 -0
- data/spec/lib/integration_spec.rb +3 -0
- data/spec/lib/rspec_extensions_spec.rb +27 -0
- data/spec/lib/wisper_spec.rb +2 -2
- data/wisper.gemspec +1 -0
- metadata +25 -25
data/README.md
CHANGED
@@ -3,10 +3,10 @@
|
|
3
3
|
Simple pub/sub for Ruby objects
|
4
4
|
|
5
5
|
[](https://codeclimate.com/github/krisleech/wisper)
|
6
|
-
[](https://travis-ci.org/krisleech/wisper)
|
6
|
+
[](https://travis-ci.org/krisleech/wisper)
|
7
7
|
|
8
8
|
While this is not dependent on Rails in any way it was extracted from a Rails
|
9
|
-
project and
|
9
|
+
project and can used as an alternative to ActiveRecord callbacks and Observers.
|
10
10
|
|
11
11
|
The problem with callbacks and Observers is that they always happen. How many
|
12
12
|
times have you wanted to do `User.create` without firing off a welcome email?
|
@@ -19,7 +19,9 @@ models.
|
|
19
19
|
|
20
20
|
Add this line to your application's Gemfile:
|
21
21
|
|
22
|
-
|
22
|
+
```ruby
|
23
|
+
gem 'wisper', '~>1.0.0'
|
24
|
+
```
|
23
25
|
|
24
26
|
## Usage
|
25
27
|
|
@@ -33,6 +35,7 @@ class MyPublisher
|
|
33
35
|
include Wisper
|
34
36
|
|
35
37
|
def do_something
|
38
|
+
# ...
|
36
39
|
publish(:done_something, self)
|
37
40
|
end
|
38
41
|
end
|
@@ -49,17 +52,17 @@ publish(:done_something, self, 'hello', 'world')
|
|
49
52
|
|
50
53
|
#### Listeners
|
51
54
|
|
52
|
-
|
55
|
+
Any object can be a listener and by default they are only subscribed to events
|
56
|
+
they can respond to.
|
53
57
|
|
54
58
|
```ruby
|
55
|
-
listener = Object.new # any object
|
56
59
|
my_publisher = MyPublisher.new
|
57
|
-
my_publisher.subscribe(
|
60
|
+
my_publisher.subscribe(MyListener.new)
|
58
61
|
```
|
59
62
|
|
60
63
|
#### Blocks
|
61
64
|
|
62
|
-
|
65
|
+
Blocks are subscribed to single events.
|
63
66
|
|
64
67
|
```ruby
|
65
68
|
my_publisher = MyPublisher.new
|
@@ -68,6 +71,23 @@ my_publisher.on(:done_something) do |publisher|
|
|
68
71
|
end
|
69
72
|
```
|
70
73
|
|
74
|
+
### Asynchronous Publishing (Experimental)
|
75
|
+
|
76
|
+
There is support for publishing events asynchronously by passing the `async`
|
77
|
+
option.
|
78
|
+
|
79
|
+
```ruby
|
80
|
+
my_publisher.add_subscriber(MySubscriber.new, :async => true)
|
81
|
+
```
|
82
|
+
|
83
|
+
This leans on Celluloid, which must be included in your Gemfile.
|
84
|
+
|
85
|
+
The listener is transparently turned in to a Celluloid Actor.
|
86
|
+
|
87
|
+
Please refer to [Celluloid](https://github.com/celluloid/celluloid/wiki)
|
88
|
+
for more information, particually the
|
89
|
+
[Gotchas](https://github.com/celluloid/celluloid/wiki/Gotchas).
|
90
|
+
|
71
91
|
### ActiveRecord
|
72
92
|
|
73
93
|
```ruby
|
@@ -103,34 +123,38 @@ class PostsController < ApplicationController
|
|
103
123
|
end
|
104
124
|
```
|
105
125
|
|
106
|
-
### Service/Use
|
107
|
-
|
108
|
-
The downside to publishing directly from ActiveRecord models is that an event
|
109
|
-
can get fired and then rolled back if a transaction fails.
|
126
|
+
### Service/Use Case/Command objects
|
110
127
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
The follow is contrived, but you can imagine it doing more than just updating a
|
115
|
-
record, maybe sending an email or updating other records.
|
128
|
+
A Service object is useful when an operation is complex, interacts with more
|
129
|
+
than one model, accesses an external API or would burden a model with too much
|
130
|
+
responsibility.
|
116
131
|
|
117
132
|
```ruby
|
118
|
-
class
|
133
|
+
class PlayerJoiningTeam
|
119
134
|
include Wisper
|
120
135
|
|
121
|
-
def execute(
|
122
|
-
|
136
|
+
def execute(player, team)
|
137
|
+
membership = Membership.new(player, team)
|
123
138
|
|
124
|
-
if
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
publish(:create_thing_successful, thing)
|
139
|
+
if membership.valid?
|
140
|
+
membership.save!
|
141
|
+
email_player(player, team)
|
142
|
+
assign_first_mission(player, team)
|
143
|
+
publish(:player_joining_team_successful, player, team)
|
130
144
|
else
|
131
|
-
publish(:
|
145
|
+
publish(:player_joining_team_failed, player, team)
|
132
146
|
end
|
133
147
|
end
|
148
|
+
|
149
|
+
private
|
150
|
+
|
151
|
+
def email_player(player, team)
|
152
|
+
# ...
|
153
|
+
end
|
154
|
+
|
155
|
+
def assign_first_mission(player, team)
|
156
|
+
# ...
|
157
|
+
end
|
134
158
|
end
|
135
159
|
```
|
136
160
|
|
@@ -157,13 +181,40 @@ class StatisticsListener
|
|
157
181
|
# ...
|
158
182
|
end
|
159
183
|
end
|
184
|
+
|
185
|
+
class CacheListener
|
186
|
+
def create_thing_successful(thing)
|
187
|
+
# ...
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
class IndexingListener
|
192
|
+
def create_thing_successful(thing)
|
193
|
+
# ...
|
194
|
+
end
|
195
|
+
end
|
160
196
|
```
|
161
197
|
|
198
|
+
## Global listeners
|
199
|
+
|
200
|
+
If you become tired of adding the same listeners to _every_ publisher you can
|
201
|
+
add global listeners. They receive all published events which they can respond
|
202
|
+
to.
|
203
|
+
|
204
|
+
However it means that when looking at the code it will not be obvious that the
|
205
|
+
global listeners are being executed in additional to the regular listeners.
|
206
|
+
|
207
|
+
```ruby
|
208
|
+
Wisper::GlobalListeners.add_listener(MyListener.new)
|
209
|
+
```
|
210
|
+
|
211
|
+
In a Rails app you might want to add your global listeners in an initalizer.
|
212
|
+
|
162
213
|
## Subscribing to selected events
|
163
214
|
|
164
|
-
By default a listener will get notified of all events it
|
165
|
-
limit which events a listener is notified of by passing an event or array
|
166
|
-
events to `:on`.
|
215
|
+
By default a listener will get notified of all events it can respond to. You
|
216
|
+
can limit which events a listener is notified of by passing an event or array
|
217
|
+
of events to `:on`.
|
167
218
|
|
168
219
|
```ruby
|
169
220
|
post_creater.subscribe(PusherListener.new, :on => :create_post_successful)
|
@@ -207,6 +258,57 @@ post.on(:success) { |post| redirect_to post }
|
|
207
258
|
.on(:failure) { |post| render :action => :edit, :locals => :post => post }
|
208
259
|
```
|
209
260
|
|
261
|
+
## RSpec
|
262
|
+
|
263
|
+
Wisper comes with a method for stubbing event publishers so that you can create isolation tests
|
264
|
+
that only care about reacting to events.
|
265
|
+
|
266
|
+
Given this piece of code:
|
267
|
+
|
268
|
+
```ruby
|
269
|
+
class CodeThatReactsToEvents
|
270
|
+
def do_something
|
271
|
+
publisher = MyPublisher.new
|
272
|
+
publisher.on(:some_event) do |variable|
|
273
|
+
return "Hello with #{variable}!"
|
274
|
+
end
|
275
|
+
publisher.execute
|
276
|
+
end
|
277
|
+
end
|
278
|
+
```
|
279
|
+
|
280
|
+
You can test it like this:
|
281
|
+
|
282
|
+
```ruby
|
283
|
+
require 'wisper/rspec/stub_wisper_publisher'
|
284
|
+
|
285
|
+
describe CodeThatReactsToEvents do
|
286
|
+
context "on some_event" do
|
287
|
+
before do
|
288
|
+
stub_wisper_publisher("MyPublisher", :execute, :some_event, "foo")
|
289
|
+
end
|
290
|
+
|
291
|
+
it "renders" do
|
292
|
+
response = CodeThatReactsToEvents.new.do_something
|
293
|
+
response.should == "Hello with foo!"
|
294
|
+
end
|
295
|
+
end
|
296
|
+
end
|
297
|
+
```
|
298
|
+
|
299
|
+
This becomes important when testing, for example, Rails controllers in
|
300
|
+
isolation from the business logic. This technique is used at the controller
|
301
|
+
layer to isolate testing the controller from testing the encapsulated business
|
302
|
+
logic.
|
303
|
+
|
304
|
+
You can use any number of args to pass to the event:
|
305
|
+
|
306
|
+
```ruby
|
307
|
+
stub_wisper_publisher("MyPublisher", :execute, :some_event, "foo1", "foo2", ...)
|
308
|
+
```
|
309
|
+
|
310
|
+
See `spec/lib/rspec_extensions_spec.rb` for a runnable example.
|
311
|
+
|
210
312
|
## Compatibility
|
211
313
|
|
212
314
|
Tested with 1.9.x on MRI, JRuby and Rubinius.
|
data/lib/wisper.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
require "wisper/version"
|
2
2
|
require "wisper/registration/registration"
|
3
3
|
require "wisper/registration/object"
|
4
|
+
require "wisper/registration/object/async_listener"
|
4
5
|
require "wisper/registration/block"
|
6
|
+
require 'wisper/global_listeners'
|
5
7
|
|
6
8
|
module Wisper
|
7
9
|
def listeners
|
@@ -29,8 +31,12 @@ module Wisper
|
|
29
31
|
|
30
32
|
private
|
31
33
|
|
34
|
+
def all_listeners
|
35
|
+
listeners.merge(GlobalListeners.listeners)
|
36
|
+
end
|
37
|
+
|
32
38
|
def broadcast(event, *args)
|
33
|
-
|
39
|
+
all_listeners.each do | listener |
|
34
40
|
listener.broadcast(clean_event(event), *args)
|
35
41
|
end
|
36
42
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
module Wisper
|
4
|
+
class GlobalListeners
|
5
|
+
include Singleton
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@listeners = Set.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def add_listener(listener, options = {})
|
12
|
+
listeners << ObjectRegistration.new(listener, options)
|
13
|
+
self
|
14
|
+
end
|
15
|
+
|
16
|
+
def listeners
|
17
|
+
@listeners
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.add_listener(listener, options = {})
|
21
|
+
instance.add_listener(listener, options)
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.listeners
|
25
|
+
instance.listeners
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -1,16 +1,27 @@
|
|
1
|
+
begin
|
2
|
+
require 'celluloid/autostart'
|
3
|
+
rescue LoadError
|
4
|
+
# no-op
|
5
|
+
end
|
6
|
+
|
1
7
|
module Wisper
|
2
8
|
class ObjectRegistration < Registration
|
3
|
-
attr_reader :with
|
9
|
+
attr_reader :with, :async
|
4
10
|
|
5
11
|
def initialize(listener, options)
|
6
12
|
super(listener, options)
|
7
|
-
@with
|
13
|
+
@with = options[:with]
|
14
|
+
@async = options.fetch(:async, false)
|
8
15
|
end
|
9
16
|
|
10
17
|
def broadcast(event, *args)
|
11
18
|
method_to_call = map_event_to_method(event)
|
12
19
|
if should_broadcast?(event) && listener.respond_to?(method_to_call)
|
13
|
-
|
20
|
+
unless async
|
21
|
+
listener.public_send(method_to_call, *args)
|
22
|
+
else
|
23
|
+
AsyncListener.new(listener, method_to_call).async.public_send(method_to_call, *args)
|
24
|
+
end
|
14
25
|
end
|
15
26
|
end
|
16
27
|
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class AsyncListener
|
2
|
+
include Celluloid if defined?(Celluloid)
|
3
|
+
|
4
|
+
attr_reader :listener, :event_method
|
5
|
+
|
6
|
+
def initialize(listener, event_method)
|
7
|
+
@listener = listener
|
8
|
+
@event_method = event_method.to_sym
|
9
|
+
end
|
10
|
+
|
11
|
+
def method_missing(method, *args, &block)
|
12
|
+
if listener.respond_to?(method)
|
13
|
+
if method == event_method
|
14
|
+
listener.public_send(method, *args, &block)
|
15
|
+
terminate
|
16
|
+
else
|
17
|
+
listener.public_send(method, *args, &block)
|
18
|
+
end
|
19
|
+
else
|
20
|
+
super(method, *args, &block)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
### Wisper Stubbing
|
2
|
+
# This is a proposal for integration as part of wisper core
|
3
|
+
# for testing: https://github.com/krisleech/wisper/issues/1
|
4
|
+
class TestWisperPublisher
|
5
|
+
include Wisper
|
6
|
+
def initialize(*args); end
|
7
|
+
end
|
8
|
+
|
9
|
+
def stub_wisper_publisher(clazz, called_method, event_to_publish, *published_event_args)
|
10
|
+
stub_const(clazz, Class.new(TestWisperPublisher) do
|
11
|
+
define_method(called_method) do
|
12
|
+
publish(event_to_publish, *published_event_args)
|
13
|
+
end
|
14
|
+
end)
|
15
|
+
end
|
data/lib/wisper/version.rb
CHANGED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class MyService
|
4
|
+
include Wisper
|
5
|
+
|
6
|
+
def execute
|
7
|
+
broadcast('success', self)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
# help me...
|
12
|
+
$global = 'no'
|
13
|
+
|
14
|
+
class MyListener
|
15
|
+
def success(command)
|
16
|
+
$global = 'yes'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe Wisper do
|
21
|
+
|
22
|
+
it 'subscribes object to all published events' do
|
23
|
+
listener = MyListener.new
|
24
|
+
|
25
|
+
command = MyService.new
|
26
|
+
|
27
|
+
command.add_listener(listener, :async => true)
|
28
|
+
|
29
|
+
command.execute
|
30
|
+
sleep(1) # seriously...
|
31
|
+
$global.should == 'yes'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Wisper::GlobalListeners do
|
4
|
+
let(:global_listener) { double('listener') }
|
5
|
+
let(:local_listener) { double('listener') }
|
6
|
+
let(:publisher) { Object.new.extend(Wisper) }
|
7
|
+
|
8
|
+
describe '.add_listener' do
|
9
|
+
it 'adds given listener to every publisher' do
|
10
|
+
Wisper::GlobalListeners.add_listener(global_listener)
|
11
|
+
global_listener.should_receive(:it_happened)
|
12
|
+
publisher.send(:broadcast, :it_happened)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'works along side local listeners' do
|
16
|
+
# global listener
|
17
|
+
Wisper::GlobalListeners.add_listener(global_listener)
|
18
|
+
|
19
|
+
# local listener
|
20
|
+
publisher.add_listener(local_listener)
|
21
|
+
|
22
|
+
global_listener.should_receive(:it_happened)
|
23
|
+
local_listener.should_receive(:it_happened)
|
24
|
+
|
25
|
+
publisher.send(:broadcast, :it_happened)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -56,7 +56,9 @@ describe Wisper do
|
|
56
56
|
|
57
57
|
it 'subscribes block can be chained' do
|
58
58
|
insider = double('Insider')
|
59
|
+
|
59
60
|
insider.should_receive(:render).with('success')
|
61
|
+
insider.should_receive(:render).with('failure')
|
60
62
|
|
61
63
|
command = MyCommand.new
|
62
64
|
|
@@ -64,5 +66,6 @@ describe Wisper do
|
|
64
66
|
.on(:failure) { |message| insider.render('failure') }
|
65
67
|
|
66
68
|
command.execute(true)
|
69
|
+
command.execute(false)
|
67
70
|
end
|
68
71
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'wisper/rspec/stub_wisper_publisher'
|
3
|
+
|
4
|
+
describe Wisper do
|
5
|
+
describe "given a piece of code invoking a publisher" do
|
6
|
+
class CodeThatReactsToEvents
|
7
|
+
def do_something
|
8
|
+
publisher = MyPublisher.new
|
9
|
+
publisher.on(:some_event) do |variable1, variable2|
|
10
|
+
return "Hello with #{variable1} #{variable2}!"
|
11
|
+
end
|
12
|
+
publisher.execute
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context "when stubbing the publisher to emit an event" do
|
17
|
+
before do
|
18
|
+
stub_wisper_publisher("MyPublisher", :execute, :some_event, "foo1", "foo2")
|
19
|
+
end
|
20
|
+
|
21
|
+
it "emits the event" do
|
22
|
+
response = CodeThatReactsToEvents.new.do_something
|
23
|
+
response.should == "Hello with foo1 foo2!"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/spec/lib/wisper_spec.rb
CHANGED
@@ -62,8 +62,9 @@ describe Wisper do
|
|
62
62
|
end
|
63
63
|
|
64
64
|
describe '.add_block_listener' do
|
65
|
+
let(:insider) { double('insider') }
|
66
|
+
|
65
67
|
it 'subscribes given block to all events' do
|
66
|
-
insider = double('insider')
|
67
68
|
insider.should_receive(:it_happened).twice
|
68
69
|
|
69
70
|
publisher.add_block_listener do
|
@@ -76,7 +77,6 @@ describe Wisper do
|
|
76
77
|
|
77
78
|
describe ':on argument' do
|
78
79
|
it '.add_block_listener subscribes block to an event' do
|
79
|
-
insider = double('insider')
|
80
80
|
insider.should_not_receive(:it_happened).once
|
81
81
|
|
82
82
|
publisher.add_block_listener(:on => 'something_happened') do
|
data/wisper.gemspec
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wisper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-05-02 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
16
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirement: &2152451840 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,15 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
25
|
-
none: false
|
26
|
-
requirements:
|
27
|
-
- - ! '>='
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: '0'
|
24
|
+
version_requirements: *2152451840
|
30
25
|
- !ruby/object:Gem::Dependency
|
31
26
|
name: rspec
|
32
|
-
requirement: !ruby/object:Gem::Requirement
|
27
|
+
requirement: &2152451300 !ruby/object:Gem::Requirement
|
33
28
|
none: false
|
34
29
|
requirements:
|
35
30
|
- - ! '>='
|
@@ -37,15 +32,10 @@ dependencies:
|
|
37
32
|
version: '0'
|
38
33
|
type: :development
|
39
34
|
prerelease: false
|
40
|
-
version_requirements:
|
41
|
-
none: false
|
42
|
-
requirements:
|
43
|
-
- - ! '>='
|
44
|
-
- !ruby/object:Gem::Version
|
45
|
-
version: '0'
|
35
|
+
version_requirements: *2152451300
|
46
36
|
- !ruby/object:Gem::Dependency
|
47
37
|
name: simplecov
|
48
|
-
requirement: !ruby/object:Gem::Requirement
|
38
|
+
requirement: &2152450760 !ruby/object:Gem::Requirement
|
49
39
|
none: false
|
50
40
|
requirements:
|
51
41
|
- - ! '>='
|
@@ -53,12 +43,18 @@ dependencies:
|
|
53
43
|
version: '0'
|
54
44
|
type: :development
|
55
45
|
prerelease: false
|
56
|
-
version_requirements:
|
46
|
+
version_requirements: *2152450760
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: celluloid
|
49
|
+
requirement: &2152450220 !ruby/object:Gem::Requirement
|
57
50
|
none: false
|
58
51
|
requirements:
|
59
52
|
- - ! '>='
|
60
53
|
- !ruby/object:Gem::Version
|
61
54
|
version: '0'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *2152450220
|
62
58
|
description: pub/sub for Ruby objects
|
63
59
|
email:
|
64
60
|
- kris.leech@gmail.com
|
@@ -74,11 +70,17 @@ files:
|
|
74
70
|
- README.md
|
75
71
|
- Rakefile
|
76
72
|
- lib/wisper.rb
|
73
|
+
- lib/wisper/global_listeners.rb
|
77
74
|
- lib/wisper/registration/block.rb
|
78
75
|
- lib/wisper/registration/object.rb
|
76
|
+
- lib/wisper/registration/object/async_listener.rb
|
79
77
|
- lib/wisper/registration/registration.rb
|
78
|
+
- lib/wisper/rspec/stub_wisper_publisher.rb
|
80
79
|
- lib/wisper/version.rb
|
80
|
+
- spec/lib/async_spec.rb
|
81
|
+
- spec/lib/global_subscribers_spec.rb
|
81
82
|
- spec/lib/integration_spec.rb
|
83
|
+
- spec/lib/rspec_extensions_spec.rb
|
82
84
|
- spec/lib/simple_example_spec.rb
|
83
85
|
- spec/lib/wisper_spec.rb
|
84
86
|
- spec/spec_helper.rb
|
@@ -95,26 +97,24 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
95
97
|
- - ! '>='
|
96
98
|
- !ruby/object:Gem::Version
|
97
99
|
version: '0'
|
98
|
-
segments:
|
99
|
-
- 0
|
100
|
-
hash: -3667309302433800657
|
101
100
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
102
101
|
none: false
|
103
102
|
requirements:
|
104
103
|
- - ! '>='
|
105
104
|
- !ruby/object:Gem::Version
|
106
105
|
version: '0'
|
107
|
-
segments:
|
108
|
-
- 0
|
109
|
-
hash: -3667309302433800657
|
110
106
|
requirements: []
|
111
107
|
rubyforge_project:
|
112
|
-
rubygems_version: 1.8.
|
108
|
+
rubygems_version: 1.8.10
|
113
109
|
signing_key:
|
114
110
|
specification_version: 3
|
115
111
|
summary: pub/sub for Ruby objects
|
116
112
|
test_files:
|
113
|
+
- spec/lib/async_spec.rb
|
114
|
+
- spec/lib/global_subscribers_spec.rb
|
117
115
|
- spec/lib/integration_spec.rb
|
116
|
+
- spec/lib/rspec_extensions_spec.rb
|
118
117
|
- spec/lib/simple_example_spec.rb
|
119
118
|
- spec/lib/wisper_spec.rb
|
120
119
|
- spec/spec_helper.rb
|
120
|
+
has_rdoc:
|