wisper-compat 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/test.yml +19 -0
  3. data/.gitignore +20 -0
  4. data/.rspec +4 -0
  5. data/.ruby-version +1 -0
  6. data/CHANGELOG.md +152 -0
  7. data/CONTRIBUTING.md +57 -0
  8. data/Gemfile +10 -0
  9. data/README.md +358 -0
  10. data/Rakefile +6 -0
  11. data/lib/wisper/broadcasters/logger_broadcaster.rb +41 -0
  12. data/lib/wisper/broadcasters/send_broadcaster.rb +9 -0
  13. data/lib/wisper/configuration.rb +44 -0
  14. data/lib/wisper/global_listeners.rb +72 -0
  15. data/lib/wisper/publisher.rb +89 -0
  16. data/lib/wisper/registration/block.rb +11 -0
  17. data/lib/wisper/registration/object.rb +43 -0
  18. data/lib/wisper/registration/registration.rb +18 -0
  19. data/lib/wisper/temporary_listeners.rb +41 -0
  20. data/lib/wisper/value_objects/events.rb +61 -0
  21. data/lib/wisper/value_objects/prefix.rb +29 -0
  22. data/lib/wisper/version.rb +3 -0
  23. data/lib/wisper.rb +65 -0
  24. data/spec/lib/global_listeners_spec.rb +82 -0
  25. data/spec/lib/integration_spec.rb +56 -0
  26. data/spec/lib/simple_example_spec.rb +21 -0
  27. data/spec/lib/temporary_global_listeners_spec.rb +103 -0
  28. data/spec/lib/wisper/broadcasters/logger_broadcaster_spec.rb +129 -0
  29. data/spec/lib/wisper/broadcasters/send_broadcaster_spec.rb +68 -0
  30. data/spec/lib/wisper/configuration/broadcasters_spec.rb +11 -0
  31. data/spec/lib/wisper/configuration_spec.rb +36 -0
  32. data/spec/lib/wisper/publisher_spec.rb +311 -0
  33. data/spec/lib/wisper/registrations/object_spec.rb +14 -0
  34. data/spec/lib/wisper/value_objects/events_spec.rb +107 -0
  35. data/spec/lib/wisper/value_objects/prefix_spec.rb +46 -0
  36. data/spec/lib/wisper_spec.rb +99 -0
  37. data/spec/spec_helper.rb +21 -0
  38. data/wisper-compat.gemspec +29 -0
  39. 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
@@ -0,0 +1,20 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ .tool-versions
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
19
+ tags
20
+ vendor
data/.rspec ADDED
@@ -0,0 +1,4 @@
1
+ --color
2
+ --format progress
3
+ --require spec_helper
4
+ --warnings
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
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ gem 'rake'
6
+ gem 'rspec'
7
+
8
+ group :extras do
9
+ gem 'yard'
10
+ end
data/README.md ADDED
@@ -0,0 +1,358 @@
1
+ # Wisper
2
+
3
+ *A micro library providing Ruby objects with Publish-Subscribe capabilities*
4
+
5
+ [![Gem Version](https://badge.fury.io/rb/wisper-compat.svg)](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,6 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new
5
+
6
+ task :default => :spec
@@ -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
@@ -0,0 +1,9 @@
1
+ module Wisper
2
+ module Broadcasters
3
+ class SendBroadcaster
4
+ def broadcast(listener, publisher, event, *args, **kwargs)
5
+ listener.public_send(event, *args, **kwargs)
6
+ end
7
+ end
8
+ end
9
+ end