wisper-compat 4.0.0
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.
- checksums.yaml +7 -0
- data/.github/workflows/test.yml +19 -0
- data/.gitignore +20 -0
- data/.rspec +4 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +152 -0
- data/CONTRIBUTING.md +57 -0
- data/Gemfile +10 -0
- data/README.md +358 -0
- data/Rakefile +6 -0
- data/lib/wisper/broadcasters/logger_broadcaster.rb +41 -0
- data/lib/wisper/broadcasters/send_broadcaster.rb +9 -0
- data/lib/wisper/configuration.rb +44 -0
- data/lib/wisper/global_listeners.rb +72 -0
- data/lib/wisper/publisher.rb +89 -0
- data/lib/wisper/registration/block.rb +11 -0
- data/lib/wisper/registration/object.rb +43 -0
- data/lib/wisper/registration/registration.rb +18 -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/lib/wisper.rb +65 -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 +103 -0
- data/spec/lib/wisper/broadcasters/logger_broadcaster_spec.rb +129 -0
- data/spec/lib/wisper/broadcasters/send_broadcaster_spec.rb +68 -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 +311 -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 +21 -0
- data/wisper-compat.gemspec +29 -0
- metadata +102 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: aaf3ed2b13cd914cd672a6dbd4807be4b15768625ca23986f5a52816787e6d2e
|
4
|
+
data.tar.gz: 987559f11ef6927aef4481bbb2221d7e5f1f7e881b82e92371440ab3ed4391df
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 30141f0611839a2e847e71b29e58f2e32615ce9786d792b0b735160a8cc3c70c0cc84b75720c6811251cd87ee494ff97d37090ca238ef054ebbe8d609d95819d
|
7
|
+
data.tar.gz: ebad69d7040bdf43ea1e45dc798c32d197c761211a19af37d5c60affd61075ba91bdbc658f59b0743a1675cc6152c3627b3662b4796de7012bea17f369d06cff
|
@@ -0,0 +1,19 @@
|
|
1
|
+
name: Test
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
|
6
|
+
jobs:
|
7
|
+
test:
|
8
|
+
name: Test
|
9
|
+
runs-on: ubuntu-latest
|
10
|
+
strategy:
|
11
|
+
matrix:
|
12
|
+
ruby: [2.7, 3.0, 3.1, 3.2]
|
13
|
+
steps:
|
14
|
+
- uses: actions/checkout@v3
|
15
|
+
- uses: ruby/setup-ruby@v1
|
16
|
+
with:
|
17
|
+
ruby-version: ${{ matrix.ruby }}
|
18
|
+
bundler-cache: true
|
19
|
+
- run: bundle exec rspec spec
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
3.2.1
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
## HEAD (unreleased)
|
2
|
+
|
3
|
+
## 4.0 (28th Feb 2023)
|
4
|
+
Authors: Jamie Schembri
|
5
|
+
|
6
|
+
* feature: rename gem from `wisper` to `wisper-compat`.
|
7
|
+
|
8
|
+
## 3.0 (20th Jan 2023)
|
9
|
+
Authors: doits, jstoks, merringtion
|
10
|
+
|
11
|
+
* Adds: Support for Ruby 3.0 keyword arguments
|
12
|
+
* Removes: Support for Ruby 2.6 and lower
|
13
|
+
|
14
|
+
## 2.0.1 (29th Aug 2019)
|
15
|
+
|
16
|
+
Authors: David Wilkie, hosseintoussi, Maxim Polunin, Tristan
|
17
|
+
Harmer, Bartosz Żurkowski, Kris Leech
|
18
|
+
|
19
|
+
* fix: support nested temporary global listeners
|
20
|
+
* docs: add threadsafe notes to README for global and temporary listeners
|
21
|
+
* docs: fix spelling mistakes in README
|
22
|
+
* fix: safely get signing key in gemspec when HOME is not set
|
23
|
+
* adds: add console to aid experiments and REPL driven development
|
24
|
+
* adds: Latest Ruby to CI
|
25
|
+
|
26
|
+
## 2.0.0 (7th Mar 2017)
|
27
|
+
|
28
|
+
Authors: Sergey Mostovoy, Andrew Kozin, Kyle Tolle, Martin, Rob Miller, Mike
|
29
|
+
Dalto, orthographic-pedant, Drew Ulmer, Mikey Hogarth, Attila Domokos, Josh
|
30
|
+
Miltz, Pascal Betz, Vasily Kolesnikov, Julien Letessier, Kris Leech
|
31
|
+
|
32
|
+
* Fix: logger raises exception if hash is passed as an argument to a listener #133, #136
|
33
|
+
* Fix: deprecation warnings #120
|
34
|
+
* Doc improvements: #106, #111, #116, #122, #128, #130, #147, #149, #150, #151
|
35
|
+
* Adds: Allow configuration of default prefix when using `prefix: true`. #105
|
36
|
+
* Adds: Allow unsubscribing of global listeners #118
|
37
|
+
* Adds: Helpful error message when passing a block to `#subscribe` of `#on` #125
|
38
|
+
* Adds: raise an error message when `#on` is not passed a block #146
|
39
|
+
* Adds: Support for JRuby 9.x #148
|
40
|
+
* Adds: Support for MRI 2.4.0 #155
|
41
|
+
* Refactor specs #126, #131
|
42
|
+
|
43
|
+
## 2.0.0.rc1 (17 Dec 2014)
|
44
|
+
|
45
|
+
Authors: Kris Leech
|
46
|
+
|
47
|
+
* remove: deprecated methods
|
48
|
+
* remove: rspec matcher and stubbing (moved to [wisper-rspec](https://github.com/krisleech/wisper-rspec))
|
49
|
+
* feature: add regexp support to `on` argument
|
50
|
+
* remove: announce alias for broadcasting
|
51
|
+
* docs: add Code of Conduct
|
52
|
+
* drop support for Ruby 1.9
|
53
|
+
|
54
|
+
## 1.6.0 (25 Oct 2014)
|
55
|
+
|
56
|
+
Authors: Kris Leech
|
57
|
+
|
58
|
+
* deprecate: add_listener, add_block_listener and respond_to
|
59
|
+
* internal: make method naming more consistent
|
60
|
+
|
61
|
+
## 1.5.0 (6th Oct 2014)
|
62
|
+
|
63
|
+
Authors: Kris Leech
|
64
|
+
|
65
|
+
* feature: allow events to be published asynchronously
|
66
|
+
* feature: broadcasting of events is plugable and configurable
|
67
|
+
* feature: broadcasters can be aliased via a symbol
|
68
|
+
* feature: logging broadcaster
|
69
|
+
|
70
|
+
## 1.4.0 (8th Sept 2014)
|
71
|
+
|
72
|
+
Authors: Kris Leech, Marc Ignacio, Ahmed Abdel Razzak, kmehkeri, Jake Hoffner
|
73
|
+
|
74
|
+
* feature: matcher for rspec 3
|
75
|
+
* fix: temporary global listeners are cleared if an exception is raised
|
76
|
+
* refactor: update all specs to rspec 3 expect syntax
|
77
|
+
* docs: update README to rspec 3 expect syntax
|
78
|
+
* feature: combine global and temporary listener methods as `Wisper.subscribe`
|
79
|
+
* deprecate: `Wisper.add_listener` and `Wisper.with_listeners,` use `Wisper.subscribe` instead
|
80
|
+
|
81
|
+
## 1.3.0 (18th Jan 2014)
|
82
|
+
|
83
|
+
Authors: Kris Leech, Yan Pritzker, Charlie Tran
|
84
|
+
|
85
|
+
* feature: global subscriptions can be scoped to a class (and sub-classes)
|
86
|
+
* upgrade: use rspec 3
|
87
|
+
* feature: allow prefixing of events with 'on'
|
88
|
+
* feature: Allow stubbed publisher method to accept arbitrary args
|
89
|
+
|
90
|
+
## 1.2.1 (7th Oct 2013)
|
91
|
+
|
92
|
+
Authors: Kris Leech, Tomasz Szymczyszyn, Alex Heeton
|
93
|
+
|
94
|
+
* feature: global subscriptions can be passed options
|
95
|
+
* docs: improve README examples
|
96
|
+
* docs: add license to gemspec
|
97
|
+
|
98
|
+
## 1.2.0 (21st July 2013)
|
99
|
+
|
100
|
+
Authors: Kris Leech, Darren Coxall
|
101
|
+
|
102
|
+
* feature: support for multiple events at once
|
103
|
+
* fix: clear global listeners after each spec
|
104
|
+
|
105
|
+
## 1.1.0 (7th June 2013)
|
106
|
+
|
107
|
+
Authors: Kris Leech, chatgris
|
108
|
+
|
109
|
+
* feature: add temporary global listeners
|
110
|
+
* docs: improve ActiveRecord example
|
111
|
+
* refactor: improve specs
|
112
|
+
* upgrade: add Ruby 2.0 support
|
113
|
+
* fix: make listener collection immutable
|
114
|
+
* remove: async publishing and Celluloid dependency
|
115
|
+
* fix: Make global listeners getter and setter threadsafe [9]
|
116
|
+
|
117
|
+
## 1.0.1 (2nd May 2013)
|
118
|
+
|
119
|
+
Authors: Kris Leech, Yan Pritzker
|
120
|
+
|
121
|
+
* feature: add async publishing using Celluloid
|
122
|
+
* docs: improve README examples
|
123
|
+
* feature: `stub_wisper_publisher` rspec helper
|
124
|
+
* feature: global listeners
|
125
|
+
* refactor: improve specs
|
126
|
+
|
127
|
+
## 1.0.0 (7th April 2013)
|
128
|
+
|
129
|
+
Authors: Kris Leech
|
130
|
+
|
131
|
+
* refactor: specs
|
132
|
+
* refactor: registrations
|
133
|
+
* feature: Add `with` argument to `subscribe`
|
134
|
+
* docs: improve README examples
|
135
|
+
* feature: Allow subscriptions to be chainable
|
136
|
+
* feature: Add `on` syntax for block subscription
|
137
|
+
* remove: Remove support for Ruby 1.8.7
|
138
|
+
* docs: Add badges to README
|
139
|
+
|
140
|
+
## 0.0.2 (30th March 2013)
|
141
|
+
|
142
|
+
Authors: Kris Leech
|
143
|
+
|
144
|
+
* remove: ActiveSupport dependency
|
145
|
+
* docs: fix syntax highlighting in README
|
146
|
+
|
147
|
+
## 0.0.1 (30th March 2013)
|
148
|
+
|
149
|
+
Authors: Kris Leech
|
150
|
+
|
151
|
+
* docs: add README
|
152
|
+
* feature: registration of objects and blocks
|
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,57 @@
|
|
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
|
+
## Questions
|
32
|
+
|
33
|
+
Try the [Wiki](https://github.com/krisleech/wisper/wiki) first, the examples
|
34
|
+
and how to sections have lots of information.
|
35
|
+
|
36
|
+
Please ask questions on StackOverflow, [tagged wisper](https://stackoverflow.com/questions/tagged/wisper).
|
37
|
+
|
38
|
+
Feel free to ping me the URL on [Twitter](https://twitter.com/krisleech).
|
39
|
+
|
40
|
+
## Pull requests
|
41
|
+
|
42
|
+
* Fork the project, create a new branch `master`.
|
43
|
+
* Squash commits which are related.
|
44
|
+
* Write a [good commit message](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html)
|
45
|
+
* Documentation only changes should have `[skip ci]` in the commit message
|
46
|
+
* Follow existing code style in terms of syntax, indentation etc.
|
47
|
+
* Add an entry to the CHANGELOG
|
48
|
+
* Do not bump the VERSION, but do indicate in the CHANGELOG if the change is
|
49
|
+
not backwards compatible.
|
50
|
+
* Issue a Pull Request
|
51
|
+
|
52
|
+
## Versions
|
53
|
+
|
54
|
+
The `v1` branch is a long lived branch and you should
|
55
|
+
branch from this if you wish to fix an issue in version `~> 1.0`.
|
56
|
+
|
57
|
+
Otherwise branch from `master` branch.
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,358 @@
|
|
1
|
+
# Wisper
|
2
|
+
|
3
|
+
*A micro library providing Ruby objects with Publish-Subscribe capabilities*
|
4
|
+
|
5
|
+
[](http://badge.fury.io/rb/wisper-compat)
|
6
|
+
|
7
|
+
* Decouple core business logic from external concerns in Hexagonal style architectures
|
8
|
+
* Use as an alternative to ActiveRecord callbacks and Observers in Rails apps
|
9
|
+
* Connect objects based on context without permanence
|
10
|
+
* Publish events synchronously or asynchronously
|
11
|
+
|
12
|
+
Note: Wisper was originally extracted from a Rails codebase but is not dependant on Rails.
|
13
|
+
|
14
|
+
Please also see the [Wiki](https://github.com/krisleech/wisper/wiki) for more additional information and articles.
|
15
|
+
|
16
|
+
**For greenfield applications you might also be interested in
|
17
|
+
[WisperNext](https://gitlab.com/kris.leech/wisper_next) and [Ma](https://gitlab.com/kris.leech/ma).**
|
18
|
+
|
19
|
+
## Installation
|
20
|
+
|
21
|
+
Add this line to your application's Gemfile:
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
gem 'wisper-compat', '4.0.0'
|
25
|
+
```
|
26
|
+
|
27
|
+
## Usage
|
28
|
+
|
29
|
+
Any class with the `Wisper::Publisher` module included can broadcast events
|
30
|
+
to subscribed listeners. Listeners subscribe, at runtime, to the publisher.
|
31
|
+
|
32
|
+
### Publishing
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
class CancelOrder
|
36
|
+
include Wisper::Publisher
|
37
|
+
|
38
|
+
def call(order_id)
|
39
|
+
order = Order.find_by_id(order_id)
|
40
|
+
|
41
|
+
# business logic...
|
42
|
+
|
43
|
+
if order.cancelled?
|
44
|
+
broadcast(:cancel_order_successful, order.id)
|
45
|
+
else
|
46
|
+
broadcast(:cancel_order_failed, order.id)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
```
|
51
|
+
|
52
|
+
When a publisher broadcasts an event it can include any number of arguments.
|
53
|
+
|
54
|
+
The `broadcast` method is also aliased as `publish`.
|
55
|
+
|
56
|
+
You can also include `Wisper.publisher` instead of `Wisper::Publisher`.
|
57
|
+
|
58
|
+
### Subscribing
|
59
|
+
|
60
|
+
#### Objects
|
61
|
+
|
62
|
+
Any object can be subscribed as a listener.
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
cancel_order = CancelOrder.new
|
66
|
+
|
67
|
+
cancel_order.subscribe(OrderNotifier.new)
|
68
|
+
|
69
|
+
cancel_order.call(order_id)
|
70
|
+
```
|
71
|
+
|
72
|
+
The listener would need to implement a method for every event it wishes to receive.
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
class OrderNotifier
|
76
|
+
def cancel_order_successful(order_id)
|
77
|
+
order = Order.find_by_id(order_id)
|
78
|
+
|
79
|
+
# notify someone ...
|
80
|
+
end
|
81
|
+
end
|
82
|
+
```
|
83
|
+
|
84
|
+
#### Blocks
|
85
|
+
|
86
|
+
Blocks can be subscribed to single events and can be chained.
|
87
|
+
|
88
|
+
```ruby
|
89
|
+
cancel_order = CancelOrder.new
|
90
|
+
|
91
|
+
cancel_order.on(:cancel_order_successful) { |order_id| ... }
|
92
|
+
.on(:cancel_order_failed) { |order_id| ... }
|
93
|
+
|
94
|
+
cancel_order.call(order_id)
|
95
|
+
```
|
96
|
+
|
97
|
+
You can also subscribe to multiple events using `on` by passing
|
98
|
+
additional events as arguments.
|
99
|
+
|
100
|
+
```ruby
|
101
|
+
cancel_order = CancelOrder.new
|
102
|
+
|
103
|
+
cancel_order.on(:cancel_order_successful) { |order_id| ... }
|
104
|
+
.on(:cancel_order_failed,
|
105
|
+
:cancel_order_invalid) { |order_id| ... }
|
106
|
+
|
107
|
+
cancel_order.call(order_id)
|
108
|
+
```
|
109
|
+
|
110
|
+
Do not `return` from inside a subscribed block, due to the way
|
111
|
+
[Ruby treats blocks](http://product.reverb.com/2015/02/28/the-strange-case-of-wisper-and-ruby-blocks-behaving-like-procs/)
|
112
|
+
this will prevent any subsequent listeners having their events delivered.
|
113
|
+
|
114
|
+
### Handling Events Asynchronously
|
115
|
+
|
116
|
+
```ruby
|
117
|
+
cancel_order.subscribe(OrderNotifier.new, async: true)
|
118
|
+
```
|
119
|
+
|
120
|
+
Wisper has various adapters for asynchronous event handling, please refer to
|
121
|
+
[wisper-celluloid](https://github.com/krisleech/wisper-celluloid),
|
122
|
+
[wisper-sidekiq](https://github.com/krisleech/wisper-sidekiq),
|
123
|
+
[wisper-activejob](https://github.com/krisleech/wisper-activejob),
|
124
|
+
[wisper-que](https://github.com/joevandyk/wisper-que) or
|
125
|
+
[wisper-resque](https://github.com/bzurkowski/wisper-resque).
|
126
|
+
|
127
|
+
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:
|
128
|
+
|
129
|
+
```ruby
|
130
|
+
class OrderNotifier
|
131
|
+
# declare a class method if you are subscribing the listener class instead of its instance like:
|
132
|
+
# cancel_order.subscribe(OrderNotifier)
|
133
|
+
#
|
134
|
+
def self.cancel_order_successful(order_id)
|
135
|
+
order = Order.find_by_id(order_id)
|
136
|
+
|
137
|
+
# notify someone ...
|
138
|
+
end
|
139
|
+
end
|
140
|
+
```
|
141
|
+
|
142
|
+
### ActionController
|
143
|
+
|
144
|
+
```ruby
|
145
|
+
class CancelOrderController < ApplicationController
|
146
|
+
|
147
|
+
def create
|
148
|
+
cancel_order = CancelOrder.new
|
149
|
+
|
150
|
+
cancel_order.subscribe(OrderMailer, async: true)
|
151
|
+
cancel_order.subscribe(ActivityRecorder, async: true)
|
152
|
+
cancel_order.subscribe(StatisticsRecorder, async: true)
|
153
|
+
|
154
|
+
cancel_order.on(:cancel_order_successful) { |order_id| redirect_to order_path(order_id) }
|
155
|
+
cancel_order.on(:cancel_order_failed) { |order_id| render action: :new }
|
156
|
+
|
157
|
+
cancel_order.call(order_id)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
```
|
161
|
+
|
162
|
+
### ActiveRecord
|
163
|
+
|
164
|
+
If you wish to publish directly from ActiveRecord models you can broadcast events from callbacks:
|
165
|
+
|
166
|
+
```ruby
|
167
|
+
class Order < ActiveRecord::Base
|
168
|
+
include Wisper::Publisher
|
169
|
+
|
170
|
+
after_commit :publish_creation_successful, on: :create
|
171
|
+
after_validation :publish_creation_failed, on: :create
|
172
|
+
|
173
|
+
private
|
174
|
+
|
175
|
+
def publish_creation_successful
|
176
|
+
broadcast(:order_creation_successful, self)
|
177
|
+
end
|
178
|
+
|
179
|
+
def publish_creation_failed
|
180
|
+
broadcast(:order_creation_failed, self) if errors.any?
|
181
|
+
end
|
182
|
+
end
|
183
|
+
```
|
184
|
+
|
185
|
+
There are more examples in the [Wiki](https://github.com/krisleech/wisper/wiki).
|
186
|
+
|
187
|
+
## Global Listeners
|
188
|
+
|
189
|
+
Global listeners receive all broadcast events which they can respond to.
|
190
|
+
|
191
|
+
This is useful for cross cutting concerns such as recording statistics, indexing, caching and logging.
|
192
|
+
|
193
|
+
```ruby
|
194
|
+
Wisper.subscribe(MyListener.new)
|
195
|
+
```
|
196
|
+
|
197
|
+
In a Rails app you might want to add your global listeners in an initializer.
|
198
|
+
|
199
|
+
Global listeners are threadsafe. Subscribers will receive events published on all threads.
|
200
|
+
|
201
|
+
|
202
|
+
### Scoping by publisher class
|
203
|
+
|
204
|
+
You might want to globally subscribe a listener to publishers with a certain
|
205
|
+
class.
|
206
|
+
|
207
|
+
```ruby
|
208
|
+
Wisper.subscribe(MyListener.new, scope: :MyPublisher)
|
209
|
+
Wisper.subscribe(MyListener.new, scope: MyPublisher)
|
210
|
+
Wisper.subscribe(MyListener.new, scope: "MyPublisher")
|
211
|
+
Wisper.subscribe(MyListener.new, scope: [:MyPublisher, :MyOtherPublisher])
|
212
|
+
```
|
213
|
+
|
214
|
+
This will subscribe the listener to all instances of the specified class(es) and their
|
215
|
+
subclasses.
|
216
|
+
|
217
|
+
Alternatively you can also do exactly the same with a publisher class itself:
|
218
|
+
|
219
|
+
```ruby
|
220
|
+
MyPublisher.subscribe(MyListener.new)
|
221
|
+
```
|
222
|
+
|
223
|
+
## Temporary Global Listeners
|
224
|
+
|
225
|
+
You can also globally subscribe listeners for the duration of a block.
|
226
|
+
|
227
|
+
```ruby
|
228
|
+
Wisper.subscribe(MyListener.new, OtherListener.new) do
|
229
|
+
# do stuff
|
230
|
+
end
|
231
|
+
```
|
232
|
+
|
233
|
+
Any events broadcast within the block by any publisher will be sent to the
|
234
|
+
listeners.
|
235
|
+
|
236
|
+
This is useful for capturing events published by objects to which you do not have access in a given context.
|
237
|
+
|
238
|
+
Temporary Global Listeners are threadsafe. Subscribers will receive events published on the same thread.
|
239
|
+
|
240
|
+
## Subscribing to selected events
|
241
|
+
|
242
|
+
By default a listener will get notified of all events it can respond to. You
|
243
|
+
can limit which events a listener is notified of by passing a string, symbol,
|
244
|
+
array or regular expression to `on`:
|
245
|
+
|
246
|
+
```ruby
|
247
|
+
post_creator.subscribe(PusherListener.new, on: :create_post_successful)
|
248
|
+
```
|
249
|
+
|
250
|
+
## Prefixing broadcast events
|
251
|
+
|
252
|
+
If you would prefer listeners to receive events with a prefix, for example
|
253
|
+
`on`, you can do so by passing a string or symbol to `prefix:`.
|
254
|
+
|
255
|
+
```ruby
|
256
|
+
post_creator.subscribe(PusherListener.new, prefix: :on)
|
257
|
+
```
|
258
|
+
|
259
|
+
If `post_creator` were to broadcast the event `post_created` the subscribed
|
260
|
+
listeners would receive `on_post_created`. You can also pass `true` which will
|
261
|
+
use the default prefix, "on".
|
262
|
+
|
263
|
+
## Mapping an event to a different method
|
264
|
+
|
265
|
+
By default the method called on the listener is the same as the event
|
266
|
+
broadcast. However it can be mapped to a different method using `with:`.
|
267
|
+
|
268
|
+
```ruby
|
269
|
+
report_creator.subscribe(MailResponder.new, with: :successful)
|
270
|
+
```
|
271
|
+
|
272
|
+
This is pretty useless unless used in conjunction with `on:`, since all events
|
273
|
+
will get mapped to `:successful`. Instead you might do something like this:
|
274
|
+
|
275
|
+
```ruby
|
276
|
+
report_creator.subscribe(MailResponder.new, on: :create_report_successful,
|
277
|
+
with: :successful)
|
278
|
+
```
|
279
|
+
|
280
|
+
If you pass an array of events to `on:` each event will be mapped to the same
|
281
|
+
method when `with:` is specified. If you need to listen for select events
|
282
|
+
_and_ map each one to a different method subscribe the listener once for
|
283
|
+
each mapping:
|
284
|
+
|
285
|
+
```ruby
|
286
|
+
report_creator.subscribe(MailResponder.new, on: :create_report_successful,
|
287
|
+
with: :successful)
|
288
|
+
|
289
|
+
report_creator.subscribe(MailResponder.new, on: :create_report_failed,
|
290
|
+
with: :failed)
|
291
|
+
```
|
292
|
+
|
293
|
+
You could also alias the method within your listener, as such
|
294
|
+
`alias successful create_report_successful`.
|
295
|
+
|
296
|
+
## Testing
|
297
|
+
|
298
|
+
Testing matchers and stubs are in separate gems.
|
299
|
+
|
300
|
+
* [wisper-rspec](https://github.com/krisleech/wisper-rspec)
|
301
|
+
* [wisper-minitest](https://github.com/digitalcuisine/wisper-minitest)
|
302
|
+
|
303
|
+
### Clearing Global Listeners
|
304
|
+
|
305
|
+
If you use global listeners in non-feature tests you _might_ want to clear them
|
306
|
+
in a hook to prevent global subscriptions persisting between tests.
|
307
|
+
|
308
|
+
```ruby
|
309
|
+
after { Wisper.clear }
|
310
|
+
```
|
311
|
+
|
312
|
+
## Need help?
|
313
|
+
|
314
|
+
The [Wiki](https://github.com/krisleech/wisper/wiki) has more examples,
|
315
|
+
articles and talks.
|
316
|
+
|
317
|
+
Got a specific question, try the
|
318
|
+
[Wisper tag on StackOverflow](http://stackoverflow.com/questions/tagged/wisper).
|
319
|
+
|
320
|
+
## Running Specs
|
321
|
+
|
322
|
+
```
|
323
|
+
bundle exec rspec
|
324
|
+
```
|
325
|
+
|
326
|
+
To run the specs on code changes try [entr](http://entrproject.org/):
|
327
|
+
|
328
|
+
```
|
329
|
+
ls **/*.rb | entr bundle exec rspec
|
330
|
+
```
|
331
|
+
|
332
|
+
## Contributing
|
333
|
+
|
334
|
+
Please read the [Contributing Guidelines](https://github.com/nedap/wisper-compat/blob/master/CONTRIBUTING.md).
|
335
|
+
|
336
|
+
## License
|
337
|
+
|
338
|
+
(The MIT License)
|
339
|
+
|
340
|
+
Copyright (c) 2013 Kris Leech
|
341
|
+
|
342
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
343
|
+
this software and associated documentation files (the 'Software'), to deal in
|
344
|
+
the Software without restriction, including without limitation the rights to
|
345
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
346
|
+
of the Software, and to permit persons to whom the Software is furnished to do
|
347
|
+
so, subject to the following conditions:
|
348
|
+
|
349
|
+
The above copyright notice and this permission notice shall be included in all
|
350
|
+
copies or substantial portions of the Software.
|
351
|
+
|
352
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
353
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
354
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
355
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
356
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
357
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
358
|
+
SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# Provides a way of wrapping another broadcaster with logging
|
2
|
+
|
3
|
+
module Wisper
|
4
|
+
module Broadcasters
|
5
|
+
class LoggerBroadcaster
|
6
|
+
def initialize(logger, broadcaster)
|
7
|
+
@logger = logger
|
8
|
+
@broadcaster = broadcaster
|
9
|
+
end
|
10
|
+
|
11
|
+
def broadcast(listener, publisher, event, *args, **kwargs)
|
12
|
+
@logger.info("[WISPER] #{name(publisher)} published #{event} to #{name(listener)} with #{args_info(args)} and #{kwargs_info(kwargs)}")
|
13
|
+
@broadcaster.broadcast(listener, publisher, event, *args, **kwargs)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def name(object)
|
19
|
+
id_method = %w(id uuid key object_id).find do |method_name|
|
20
|
+
object.respond_to?(method_name) && object.method(method_name).arity <= 0
|
21
|
+
end
|
22
|
+
id = object.send(id_method)
|
23
|
+
class_name = object.class == Class ? object.name : object.class.name
|
24
|
+
"#{class_name}##{id}"
|
25
|
+
end
|
26
|
+
|
27
|
+
def args_info(args)
|
28
|
+
return 'no arguments' if args.empty?
|
29
|
+
args.map do |arg|
|
30
|
+
arg_string = name(arg)
|
31
|
+
arg_string += ": #{arg.inspect}" if [Numeric, Array, Hash, String].any? {|klass| arg.is_a?(klass) }
|
32
|
+
arg_string
|
33
|
+
end.join(', ')
|
34
|
+
end
|
35
|
+
|
36
|
+
def kwargs_info(kwargs)
|
37
|
+
kwargs.empty? ? 'no keyword arguments' : "keyword arguments #{kwargs.inspect}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|