siftery-wisper 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +21 -0
- data/.rspec +4 -0
- data/.travis.yml +22 -0
- data/CHANGELOG.md +129 -0
- data/CONTRIBUTING.md +61 -0
- data/Gemfile +13 -0
- data/README.md +373 -0
- data/Rakefile +10 -0
- data/bin/console +8 -0
- data/bin/setup +6 -0
- data/gem-public_cert.pem +21 -0
- data/lib/wisper.rb +65 -0
- data/lib/wisper/broadcasters/logger_broadcaster.rb +37 -0
- data/lib/wisper/broadcasters/send_broadcaster.rb +9 -0
- data/lib/wisper/configuration.rb +44 -0
- data/lib/wisper/global_listeners.rb +74 -0
- data/lib/wisper/publisher.rb +89 -0
- data/lib/wisper/registration/block.rb +11 -0
- data/lib/wisper/registration/object.rb +77 -0
- data/lib/wisper/registration/registration.rb +19 -0
- data/lib/wisper/temporary_listeners.rb +41 -0
- data/lib/wisper/value_objects/events.rb +61 -0
- data/lib/wisper/value_objects/prefix.rb +29 -0
- data/lib/wisper/version.rb +3 -0
- data/siftery-wisper.gemspec +31 -0
- data/spec/lib/global_listeners_spec.rb +82 -0
- data/spec/lib/integration_spec.rb +56 -0
- data/spec/lib/simple_example_spec.rb +21 -0
- data/spec/lib/temporary_global_listeners_spec.rb +67 -0
- data/spec/lib/wisper/broadcasters/logger_broadcaster_spec.rb +93 -0
- data/spec/lib/wisper/broadcasters/send_broadcaster_spec.rb +28 -0
- data/spec/lib/wisper/configuration/broadcasters_spec.rb +11 -0
- data/spec/lib/wisper/configuration_spec.rb +36 -0
- data/spec/lib/wisper/publisher_spec.rb +331 -0
- data/spec/lib/wisper/registrations/object_spec.rb +14 -0
- data/spec/lib/wisper/value_objects/events_spec.rb +107 -0
- data/spec/lib/wisper/value_objects/prefix_spec.rb +46 -0
- data/spec/lib/wisper_spec.rb +99 -0
- data/spec/spec_helper.rb +24 -0
- metadata +101 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 4f6bf677ec7224bac38caa11cb49620dedb6a0e2d28095b940bc0f6e1563d54b
|
4
|
+
data.tar.gz: 7007c32fce8fdc5ceebb740c965210dab06cd4ba12ff6e639d671e705252d296
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 0b39cec008bc8bae5b15e560a225b99afda15db75ebffdb81602642ca6734636fe8d903958ed2dd0a187926643a55c06a0ed7f2daa76180b0b4889d35fdf2401
|
7
|
+
data.tar.gz: 03dd49ce611320e862a6af823e8a58eaad516d8d336eae5aafedd60db7d2f96555e801c0db05f241d3dbb92125e3172b7000dc64fcee532414e34f8736949f04
|
data/.gitignore
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.ruby-version
|
4
|
+
.ruby-gemspec
|
5
|
+
.bundle
|
6
|
+
.config
|
7
|
+
.yardoc
|
8
|
+
Gemfile.lock
|
9
|
+
InstalledFiles
|
10
|
+
_yardoc
|
11
|
+
coverage
|
12
|
+
doc/
|
13
|
+
lib/bundler/man
|
14
|
+
pkg
|
15
|
+
rdoc
|
16
|
+
spec/reports
|
17
|
+
test/tmp
|
18
|
+
test/version_tmp
|
19
|
+
tmp
|
20
|
+
tags
|
21
|
+
vendor
|
data/.rspec
ADDED
data/.travis.yml
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
language: ruby
|
2
|
+
before_install:
|
3
|
+
- gem update --system
|
4
|
+
- gem update bundler
|
5
|
+
bundler_args: --without=extras
|
6
|
+
script: rspec spec
|
7
|
+
sudo: false
|
8
|
+
rvm:
|
9
|
+
- '2.1.10'
|
10
|
+
- '2.2.6'
|
11
|
+
- '2.3.3'
|
12
|
+
- '2.4.0'
|
13
|
+
- jruby-9.1.6.0
|
14
|
+
# - rbx-2
|
15
|
+
### ALLOWED FAILURES ###
|
16
|
+
# see how compatible we are with dev versions, but do not fail the build
|
17
|
+
- ruby-head
|
18
|
+
- jruby-head
|
19
|
+
matrix:
|
20
|
+
allow_failures:
|
21
|
+
- rvm: ruby-head
|
22
|
+
- rvm: jruby-head
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
## HEAD (unreleased)
|
2
|
+
|
3
|
+
## 2.0.0 (7th Mar 2017)
|
4
|
+
|
5
|
+
Authors: Sergey Mostovoy, Andrew Kozin, Kyle Tolle, Martin, Rob Miller, Mike
|
6
|
+
Dalto, orthographic-pedant, Drew Ulmer, Mikey Hogarth, Attila Domokos, Josh
|
7
|
+
Miltz, Pascal Betz, Vasily Kolesnikov, Julien Letessier, Kris Leech
|
8
|
+
|
9
|
+
* Fix: logger raises exception if hash is passed as an argument to a listener #133, #136
|
10
|
+
* Fix: deprecation warnings #120
|
11
|
+
* Doc improvements: #106, #111, #116, #122, #128, #130, #147, #149, #150, #151
|
12
|
+
* Adds: Allow configuration of default prefix when using `prefix: true`. #105
|
13
|
+
* Adds: Allow unsubscribing of global listeners #118
|
14
|
+
* Adds: Helpful error message when passing a block to `#subscribe` of `#on` #125
|
15
|
+
* Adds: raise an error message when `#on` is not passed a block #146
|
16
|
+
* Adds: Support for JRuby 9.x #148
|
17
|
+
* Adds: Support for MRI 2.4.0 #155
|
18
|
+
* Refactor specs #126, #131
|
19
|
+
|
20
|
+
## 2.0.0.rc1 (17 Dec 2014)
|
21
|
+
|
22
|
+
Authors: Kris Leech
|
23
|
+
|
24
|
+
* remove: deprecated methods
|
25
|
+
* remove: rspec matcher and stubbing (moved to [wisper-rspec](https://github.com/krisleech/wisper-rspec))
|
26
|
+
* feature: add regexp support to `on` argument
|
27
|
+
* remove: announce alias for broadcasting
|
28
|
+
* docs: add Code of Conduct
|
29
|
+
* drop support for Ruby 1.9
|
30
|
+
|
31
|
+
## 1.6.0 (25 Oct 2014)
|
32
|
+
|
33
|
+
Authors: Kris Leech
|
34
|
+
|
35
|
+
* deprecate: add_listener, add_block_listener and respond_to
|
36
|
+
* internal: make method naming more consistent
|
37
|
+
|
38
|
+
## 1.5.0 (6th Oct 2014)
|
39
|
+
|
40
|
+
Authors: Kris Leech
|
41
|
+
|
42
|
+
* feature: allow events to be published asynchronously
|
43
|
+
* feature: broadcasting of events is plugable and configurable
|
44
|
+
* feature: broadcasters can be aliased via a symbol
|
45
|
+
* feature: logging broadcaster
|
46
|
+
|
47
|
+
## 1.4.0 (8th Sept 2014)
|
48
|
+
|
49
|
+
Authors: Kris Leech, Marc Ignacio, Ahmed Abdel Razzak, kmehkeri, Jake Hoffner
|
50
|
+
|
51
|
+
* feature: matcher for rspec 3
|
52
|
+
* fix: temporary global listeners are cleared if an exception is raised
|
53
|
+
* refactor: update all specs to rspec 3 expect syntax
|
54
|
+
* docs: update README to rspec 3 expect syntax
|
55
|
+
* feature: combine global and temporary listener methods as `Wisper.subscribe`
|
56
|
+
* deprecate: `Wisper.add_listener` and `Wisper.with_listeners,` use `Wisper.subscribe` instead
|
57
|
+
|
58
|
+
## 1.3.0 (18th Jan 2014)
|
59
|
+
|
60
|
+
Authors: Kris Leech, Yan Pritzker, Charlie Tran
|
61
|
+
|
62
|
+
* feature: global subscriptions can be scoped to a class (and sub-classes)
|
63
|
+
* upgrade: use rspec 3
|
64
|
+
* feature: allow prefixing of events with 'on'
|
65
|
+
* feature: Allow stubbed publisher method to accept arbitrary args
|
66
|
+
|
67
|
+
## 1.2.1 (7th Oct 2013)
|
68
|
+
|
69
|
+
Authors: Kris Leech, Tomasz Szymczyszyn, Alex Heeton
|
70
|
+
|
71
|
+
* feature: global subscriptions can be passed options
|
72
|
+
* docs: improve README examples
|
73
|
+
* docs: add license to gemspec
|
74
|
+
|
75
|
+
## 1.2.0 (21st July 2013)
|
76
|
+
|
77
|
+
Authors: Kris Leech, Darren Coxall
|
78
|
+
|
79
|
+
* feature: support for multiple events at once
|
80
|
+
* fix: clear global listeners after each spec
|
81
|
+
|
82
|
+
## 1.1.0 (7th June 2013)
|
83
|
+
|
84
|
+
Authors: Kris Leech, chatgris
|
85
|
+
|
86
|
+
* feature: add temporary global listeners
|
87
|
+
* docs: improve ActiveRecord example
|
88
|
+
* refactor: improve specs
|
89
|
+
* upgrade: add Ruby 2.0 support
|
90
|
+
* fix: make listener collection immutable
|
91
|
+
* remove: async publishing and Celluloid dependency
|
92
|
+
* fix: Make global listeners getter and setter threadsafe [9]
|
93
|
+
|
94
|
+
## 1.0.1 (2nd May 2013)
|
95
|
+
|
96
|
+
Authors: Kris Leech, Yan Pritzker
|
97
|
+
|
98
|
+
* feature: add async publishing using Celluloid
|
99
|
+
* docs: improve README examples
|
100
|
+
* feature: `stub_wisper_publisher` rspec helper
|
101
|
+
* feature: global listeners
|
102
|
+
* refactor: improve specs
|
103
|
+
|
104
|
+
## 1.0.0 (7th April 2013)
|
105
|
+
|
106
|
+
Authors: Kris Leech
|
107
|
+
|
108
|
+
* refactor: specs
|
109
|
+
* refactor: registrations
|
110
|
+
* feature: Add `with` argument to `subscribe`
|
111
|
+
* docs: improve README examples
|
112
|
+
* feature: Allow subscriptions to be chainable
|
113
|
+
* feature: Add `on` syntax for block subscription
|
114
|
+
* remove: Remove support for Ruby 1.8.7
|
115
|
+
* docs: Add badges to README
|
116
|
+
|
117
|
+
## 0.0.2 (30th March 2013)
|
118
|
+
|
119
|
+
Authors: Kris Leech
|
120
|
+
|
121
|
+
* remove: ActiveSupport dependency
|
122
|
+
* docs: fix syntax highlighting in README
|
123
|
+
|
124
|
+
## 0.0.1 (30th March 2013)
|
125
|
+
|
126
|
+
Authors: Kris Leech
|
127
|
+
|
128
|
+
* docs: add README
|
129
|
+
* feature: registration of objects and blocks
|
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
# How to Contribute
|
2
|
+
|
3
|
+
We very much welcome contributions to Wisper.
|
4
|
+
|
5
|
+
This project is intended to be a safe, welcoming space for collaboration,
|
6
|
+
and contributors are expected to adhere to the
|
7
|
+
[Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
8
|
+
|
9
|
+
## Getting started
|
10
|
+
|
11
|
+
Please first check the existing [Issues](https://github.com/krisleech/wisper/issues)
|
12
|
+
and [Pull Requests](https://github.com/krisleech/wisper/pulls) to ensure your
|
13
|
+
issue has not already been discused.
|
14
|
+
|
15
|
+
## Bugs
|
16
|
+
|
17
|
+
Please submit a bug report to the issue tracker, with the version of Wisper
|
18
|
+
and Ruby you are using and a small code sample (or better yet a failing test).
|
19
|
+
|
20
|
+
## Features
|
21
|
+
|
22
|
+
Please open an issue with your proposed feature. We can discuss the feature and
|
23
|
+
if it is acceptable we can also discuss implimentation details. You will in
|
24
|
+
most cases have to submit a PR which adds the feature.
|
25
|
+
|
26
|
+
Wisper is a micro library and will remain lean. Some features would be most
|
27
|
+
appropriate as an extension to Wisper.
|
28
|
+
|
29
|
+
We also have a [Gitter channel](https://gitter.im/krisleech/wisper) if you wish to discuss your ideas.
|
30
|
+
|
31
|
+
## Backlog / Roadmap
|
32
|
+
|
33
|
+
The backlog for Wisper and related gems is on [Waffle](https://waffle.io/krisleech/wisper).
|
34
|
+
|
35
|
+
## Questions
|
36
|
+
|
37
|
+
Try the [Wiki](https://github.com/krisleech/wisper/wiki) first, the examples
|
38
|
+
and how to sections have lots of information.
|
39
|
+
|
40
|
+
Please ask questions on StackOverflow, [tagged wisper](https://stackoverflow.com/questions/tagged/wisper).
|
41
|
+
|
42
|
+
Feel free to ping me the URL on [Twitter](https://twitter.com/krisleech).
|
43
|
+
|
44
|
+
## Pull requests
|
45
|
+
|
46
|
+
* Fork the project, create a new branch from `v1` or `master`.
|
47
|
+
* Squash commits which are related.
|
48
|
+
* Write a [good commit message](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html)
|
49
|
+
* Documentation only changes should have `[skip ci]` in the commit message
|
50
|
+
* Follow existing code style in terms of syntax, indentation etc.
|
51
|
+
* Add an entry to the CHANGELOG
|
52
|
+
* Do not bump the VERSION, but do indicate in the CHANGELOG if the change is
|
53
|
+
not backwards compatible.
|
54
|
+
* Issue a Pull Request
|
55
|
+
|
56
|
+
## Versions
|
57
|
+
|
58
|
+
The `v1` branch is a long lived branch and you should
|
59
|
+
branch from this if you wish to fix an issue in version `~> 1.0`.
|
60
|
+
|
61
|
+
The `master` branch will target the next version of Wisper.
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,373 @@
|
|
1
|
+
# Wisper
|
2
|
+
|
3
|
+
*A micro library providing Ruby objects with Publish-Subscribe capabilities*
|
4
|
+
|
5
|
+
[![Gem Version](https://badge.fury.io/rb/wisper.svg)](http://badge.fury.io/rb/wisper)
|
6
|
+
[![Code Climate](https://codeclimate.com/github/krisleech/wisper.svg)](https://codeclimate.com/github/krisleech/wisper)
|
7
|
+
[![Build Status](https://travis-ci.org/krisleech/wisper.svg?branch=master)](https://travis-ci.org/krisleech/wisper)
|
8
|
+
[![Coverage Status](https://coveralls.io/repos/krisleech/wisper/badge.svg?branch=master)](https://coveralls.io/r/krisleech/wisper?branch=master)
|
9
|
+
|
10
|
+
* Decouple core business logic from external concerns in Hexagonal style architectures
|
11
|
+
* Use as an alternative to ActiveRecord callbacks and Observers in Rails apps
|
12
|
+
* Connect objects based on context without permanence
|
13
|
+
* React to events synchronously or asynchronously
|
14
|
+
|
15
|
+
Note: Wisper was originally extracted from a Rails codebase but is not dependant on Rails.
|
16
|
+
|
17
|
+
## Installation
|
18
|
+
|
19
|
+
Add this line to your application's Gemfile:
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
gem 'wisper', '2.0.0'
|
23
|
+
```
|
24
|
+
|
25
|
+
## Usage
|
26
|
+
|
27
|
+
Any class with the `Wisper::Publisher` module included can broadcast events
|
28
|
+
to subscribed listeners. Listeners subscribe, at runtime, to the publisher.
|
29
|
+
|
30
|
+
### Publishing
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
class CancelOrder
|
34
|
+
include Wisper::Publisher
|
35
|
+
|
36
|
+
def call(order_id)
|
37
|
+
order = Order.find_by_id(order_id)
|
38
|
+
|
39
|
+
# business logic...
|
40
|
+
|
41
|
+
if order.cancelled?
|
42
|
+
broadcast(:cancel_order_successful, order.id)
|
43
|
+
else
|
44
|
+
broadcast(:cancel_order_failed, order.id)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
```
|
49
|
+
|
50
|
+
When a publisher broadcasts an event it can include any number of arguments.
|
51
|
+
|
52
|
+
The `broadcast` method is also aliased as `publish`.
|
53
|
+
|
54
|
+
You can also include `Wisper.publisher` instead of `Wisper::Publisher`.
|
55
|
+
|
56
|
+
### Subscribing
|
57
|
+
|
58
|
+
#### Objects
|
59
|
+
|
60
|
+
Any object can be subscribed as a listener.
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
cancel_order = CancelOrder.new
|
64
|
+
|
65
|
+
cancel_order.subscribe(OrderNotifier.new)
|
66
|
+
|
67
|
+
cancel_order.call(order_id)
|
68
|
+
```
|
69
|
+
|
70
|
+
The listener would need to implement a method for every event it wishes to receive.
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
class OrderNotifier
|
74
|
+
def cancel_order_successful(order_id)
|
75
|
+
order = Order.find_by_id(order_id)
|
76
|
+
|
77
|
+
# notify someone ...
|
78
|
+
end
|
79
|
+
end
|
80
|
+
```
|
81
|
+
|
82
|
+
#### Blocks
|
83
|
+
|
84
|
+
Blocks can be subscribed to single events and can be chained.
|
85
|
+
|
86
|
+
```ruby
|
87
|
+
cancel_order = CancelOrder.new
|
88
|
+
|
89
|
+
cancel_order.on(:cancel_order_successful) { |order_id| ... }
|
90
|
+
.on(:cancel_order_failed) { |order_id| ... }
|
91
|
+
|
92
|
+
cancel_order.call(order_id)
|
93
|
+
```
|
94
|
+
|
95
|
+
You can also subscribe to multiple events using `on` by passing
|
96
|
+
additional events as arguments.
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
cancel_order = CancelOrder.new
|
100
|
+
|
101
|
+
cancel_order.on(:cancel_order_successful) { |order_id| ... }
|
102
|
+
.on(:cancel_order_failed,
|
103
|
+
:cancel_order_invalid) { |order_id| ... }
|
104
|
+
|
105
|
+
cancel_order.call(order_id)
|
106
|
+
```
|
107
|
+
|
108
|
+
Do not `return` from inside a subscribed block, due to the way
|
109
|
+
[Ruby treats blocks](http://product.reverb.com/2015/02/28/the-strange-case-of-wisper-and-ruby-blocks-behaving-like-procs/)
|
110
|
+
this will prevent any subsequent listeners having their events delivered.
|
111
|
+
|
112
|
+
### Handling Events Asynchronously
|
113
|
+
|
114
|
+
```ruby
|
115
|
+
cancel_order.subscribe(OrderNotifier.new, async: true)
|
116
|
+
```
|
117
|
+
|
118
|
+
You can also pass additional configuration options to the job using the following syntax:
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
cancel_order.subscribe(OrderNotifier.new, async: { queue: 'custom', retry: false })
|
122
|
+
```
|
123
|
+
|
124
|
+
The list of supported handler options is determined by adapter
|
125
|
+
|
126
|
+
Wisper has various adapters for asynchronous event handling, please refer to
|
127
|
+
[wisper-celluloid](https://github.com/krisleech/wisper-celluloid),
|
128
|
+
[wisper-sidekiq](https://github.com/krisleech/wisper-sidekiq),
|
129
|
+
[wisper-activejob](https://github.com/krisleech/wisper-activejob), or
|
130
|
+
[wisper-que](https://github.com/joevandyk/wisper-que).
|
131
|
+
|
132
|
+
Depending on the adapter used the listener may need to be a class instead of an object. In this situation, every method corresponding to events should be declared as a class method, too. For example:
|
133
|
+
|
134
|
+
```ruby
|
135
|
+
class OrderNotifier
|
136
|
+
# declare a class method if you are subscribing the listener class instead of its instance like:
|
137
|
+
# cancel_order.subscribe(OrderNotifier)
|
138
|
+
#
|
139
|
+
def self.cancel_order_successful(order_id)
|
140
|
+
order = Order.find_by_id(order_id)
|
141
|
+
|
142
|
+
# notify someone ...
|
143
|
+
end
|
144
|
+
end
|
145
|
+
```
|
146
|
+
|
147
|
+
### ActionController
|
148
|
+
|
149
|
+
```ruby
|
150
|
+
class CancelOrderController < ApplicationController
|
151
|
+
|
152
|
+
def create
|
153
|
+
cancel_order = CancelOrder.new
|
154
|
+
|
155
|
+
cancel_order.subscribe(OrderMailer, async: true)
|
156
|
+
cancel_order.subscribe(ActivityRecorder, async: true)
|
157
|
+
cancel_order.subscribe(StatisticsRecorder, async: true)
|
158
|
+
|
159
|
+
cancel_order.on(:cancel_order_successful) { |order_id| redirect_to order_path(order_id) }
|
160
|
+
cancel_order.on(:cancel_order_failed) { |order_id| render action: :new }
|
161
|
+
|
162
|
+
cancel_order.call(order_id)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
```
|
166
|
+
|
167
|
+
### ActiveRecord
|
168
|
+
|
169
|
+
If you wish to publish directly from ActiveRecord models you can broadcast events from callbacks:
|
170
|
+
|
171
|
+
```ruby
|
172
|
+
class Order < ActiveRecord::Base
|
173
|
+
include Wisper::Publisher
|
174
|
+
|
175
|
+
after_commit :publish_creation_successful, on: :create
|
176
|
+
after_validation :publish_creation_failed, on: :create
|
177
|
+
|
178
|
+
private
|
179
|
+
|
180
|
+
def publish_creation_successful
|
181
|
+
broadcast(:order_creation_successful, self)
|
182
|
+
end
|
183
|
+
|
184
|
+
def publish_creation_failed
|
185
|
+
broadcast(:order_creation_failed, self) if errors.any?
|
186
|
+
end
|
187
|
+
end
|
188
|
+
```
|
189
|
+
|
190
|
+
There are more examples in the [Wiki](https://github.com/krisleech/wisper/wiki).
|
191
|
+
|
192
|
+
## Global Listeners
|
193
|
+
|
194
|
+
Global listeners receive all broadcast events which they can respond to.
|
195
|
+
|
196
|
+
This is useful for cross cutting concerns such as recording statistics, indexing, caching and logging.
|
197
|
+
|
198
|
+
```ruby
|
199
|
+
Wisper.subscribe(MyListener.new)
|
200
|
+
```
|
201
|
+
|
202
|
+
In a Rails app you might want to add your global listeners in an initalizer.
|
203
|
+
|
204
|
+
Global listeners are threadsafe.
|
205
|
+
|
206
|
+
### Scoping by publisher class
|
207
|
+
|
208
|
+
You might want to globally subscribe a listener to publishers with a certain
|
209
|
+
class.
|
210
|
+
|
211
|
+
```ruby
|
212
|
+
Wisper.subscribe(MyListener.new, scope: :MyPublisher)
|
213
|
+
Wisper.subscribe(MyListener.new, scope: MyPublisher)
|
214
|
+
Wisper.subscribe(MyListener.new, scope: "MyPublisher")
|
215
|
+
Wisper.subscribe(MyListener.new, scope: [:MyPublisher, :MyOtherPublisher])
|
216
|
+
```
|
217
|
+
|
218
|
+
This will subscribe the listener to all instances of the specified class(es) and their
|
219
|
+
subclasses.
|
220
|
+
|
221
|
+
Alternatively you can also do exactly the same with a publisher class itself:
|
222
|
+
|
223
|
+
```ruby
|
224
|
+
MyPublisher.subscribe(MyListener.new)
|
225
|
+
```
|
226
|
+
|
227
|
+
## Temporary Global Listeners
|
228
|
+
|
229
|
+
You can also globally subscribe listeners for the duration of a block.
|
230
|
+
|
231
|
+
```ruby
|
232
|
+
Wisper.subscribe(MyListener.new, OtherListener.new) do
|
233
|
+
# do stuff
|
234
|
+
end
|
235
|
+
```
|
236
|
+
|
237
|
+
Any events broadcast within the block by any publisher will be sent to the
|
238
|
+
listeners.
|
239
|
+
|
240
|
+
This is useful for capturing events published by objects to which you do not have access in a given context.
|
241
|
+
|
242
|
+
Temporary Global Listeners are threadsafe.
|
243
|
+
|
244
|
+
## Subscribing to selected events
|
245
|
+
|
246
|
+
By default a listener will get notified of all events it can respond to. You
|
247
|
+
can limit which events a listener is notified of by passing a string, symbol,
|
248
|
+
array or regular expression to `on`:
|
249
|
+
|
250
|
+
```ruby
|
251
|
+
post_creator.subscribe(PusherListener.new, on: :create_post_successful)
|
252
|
+
```
|
253
|
+
|
254
|
+
## Prefixing broadcast events
|
255
|
+
|
256
|
+
If you would prefer listeners to receive events with a prefix, for example
|
257
|
+
`on`, you can do so by passing a string or symbol to `prefix:`.
|
258
|
+
|
259
|
+
```ruby
|
260
|
+
post_creator.subscribe(PusherListener.new, prefix: :on)
|
261
|
+
```
|
262
|
+
|
263
|
+
If `post_creator` were to broadcast the event `post_created` the subscribed
|
264
|
+
listeners would receive `on_post_created`. You can also pass `true` which will
|
265
|
+
use the default prefix, "on".
|
266
|
+
|
267
|
+
## Mapping an event to a different method
|
268
|
+
|
269
|
+
By default the method called on the listener is the same as the event
|
270
|
+
broadcast. However it can be mapped to a different method using `with:`.
|
271
|
+
|
272
|
+
```ruby
|
273
|
+
report_creator.subscribe(MailResponder.new, with: :successful)
|
274
|
+
```
|
275
|
+
|
276
|
+
This is pretty useless unless used in conjunction with `on:`, since all events
|
277
|
+
will get mapped to `:successful`. Instead you might do something like this:
|
278
|
+
|
279
|
+
```ruby
|
280
|
+
report_creator.subscribe(MailResponder.new, on: :create_report_successful,
|
281
|
+
with: :successful)
|
282
|
+
```
|
283
|
+
|
284
|
+
If you pass an array of events to `on:` each event will be mapped to the same
|
285
|
+
method when `with:` is specified. If you need to listen for select events
|
286
|
+
_and_ map each one to a different method subscribe the listener once for
|
287
|
+
each mapping:
|
288
|
+
|
289
|
+
```ruby
|
290
|
+
report_creator.subscribe(MailResponder.new, on: :create_report_successful,
|
291
|
+
with: :successful)
|
292
|
+
|
293
|
+
report_creator.subscribe(MailResponder.new, on: :create_report_failed,
|
294
|
+
with: :failed)
|
295
|
+
```
|
296
|
+
|
297
|
+
You could also alias the method within your listener, as such
|
298
|
+
`alias successful create_report_successful`.
|
299
|
+
|
300
|
+
## Testing
|
301
|
+
|
302
|
+
Testing matchers and stubs are in seperate gems.
|
303
|
+
|
304
|
+
* [wisper-rspec](https://github.com/krisleech/wisper-rspec)
|
305
|
+
* [wisper-minitest](https://github.com/digitalcuisine/wisper-minitest)
|
306
|
+
|
307
|
+
### Clearing Global Listeners
|
308
|
+
|
309
|
+
If you use global listeners in non-feature tests you _might_ want to clear them
|
310
|
+
in a hook to prevent global subscriptions persisting between tests.
|
311
|
+
|
312
|
+
```ruby
|
313
|
+
after { Wisper.clear }
|
314
|
+
```
|
315
|
+
|
316
|
+
## Need help?
|
317
|
+
|
318
|
+
The [Wiki](https://github.com/krisleech/wisper/wiki) has more examples,
|
319
|
+
articles and talks.
|
320
|
+
|
321
|
+
Got a specific question, try the
|
322
|
+
[Wisper tag on StackOverflow](http://stackoverflow.com/questions/tagged/wisper).
|
323
|
+
|
324
|
+
## Compatibility
|
325
|
+
|
326
|
+
Tested with MRI 2.x, JRuby and Rubinius.
|
327
|
+
|
328
|
+
See the [build status](https://travis-ci.org/krisleech/wisper) for details.
|
329
|
+
|
330
|
+
## Running Specs
|
331
|
+
|
332
|
+
```
|
333
|
+
bundle exec rspec
|
334
|
+
```
|
335
|
+
|
336
|
+
To run the specs on code changes try [entr](http://entrproject.org/):
|
337
|
+
|
338
|
+
```
|
339
|
+
ls **/*.rb | entr bundle exec rspec
|
340
|
+
```
|
341
|
+
|
342
|
+
## Contributing
|
343
|
+
|
344
|
+
Please read the [Contributing Guidelines](https://github.com/krisleech/wisper/blob/master/CONTRIBUTING.md).
|
345
|
+
|
346
|
+
## Security
|
347
|
+
|
348
|
+
* gem releases are [signed](http://guides.rubygems.org/security/) ([public key](https://github.com/krisleech/wisper/blob/master/gem-public_cert.pem))
|
349
|
+
* commits are GPG signed ([public key](https://pgp.mit.edu/pks/lookup?op=get&search=0x3ABC74851F7CCC88))
|
350
|
+
|
351
|
+
## License
|
352
|
+
|
353
|
+
(The MIT License)
|
354
|
+
|
355
|
+
Copyright (c) 2013 Kris Leech
|
356
|
+
|
357
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
358
|
+
this software and associated documentation files (the 'Software'), to deal in
|
359
|
+
the Software without restriction, including without limitation the rights to
|
360
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
361
|
+
of the Software, and to permit persons to whom the Software is furnished to do
|
362
|
+
so, subject to the following conditions:
|
363
|
+
|
364
|
+
The above copyright notice and this permission notice shall be included in all
|
365
|
+
copies or substantial portions of the Software.
|
366
|
+
|
367
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
368
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
369
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
370
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
371
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
372
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
373
|
+
SOFTWARE.
|