wisper 2.0.0.rc1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e196cad72b441abfb2aa87211e0241729dbfe803
4
- data.tar.gz: d1506f6acdac8f354ab801814c73726933201abd
3
+ metadata.gz: 62cd6c2948137446de8f7f515bcbebd11c14092d
4
+ data.tar.gz: dfbc3b2d28c9023edc9f8308a6c406887c20efed
5
5
  SHA512:
6
- metadata.gz: 2f1fee408008e32f3861df1438edec17fb05e599e1bb6a196e6c288a5def62d8736d9d7667e22089bee64dae89e54f3d2a8615ecbba24a37efdd6aa23e0fb41d
7
- data.tar.gz: b6f4e0b0bdfd905c8ae1562ca79f2c7606804de8ee7e23c4d378019ff780cb3176c1467752b6ec61ee16499658fe9de48bf1b8611da590bdf29bb8d89dcd5b9b
6
+ metadata.gz: d82be662081f118b83ce5f01f87a0760be1bbc9d711163fc76ac303db689ba307ec453afb9edfb374fa1b23e92ab6a684a2c3857580d3f6a29195c75c8d6f754
7
+ data.tar.gz: 9395fbd3e0d2b925d31dc06682aa573ad66b0f4ee980533b1671e497ce7f2b8b82019840c7f8eb15c7f52b7bdae73934592ae0e5634729b4ad99f2c068bcae3e
data/.gitignore CHANGED
@@ -17,3 +17,4 @@ test/tmp
17
17
  test/version_tmp
18
18
  tmp
19
19
  tags
20
+ vendor
@@ -1,17 +1,22 @@
1
1
  language: ruby
2
+ before_install:
3
+ - gem update --system
4
+ - gem update bundler
2
5
  bundler_args: --without=extras
3
6
  script: rspec spec
7
+ sudo: false
4
8
  rvm:
5
- - '1.9.2'
6
- - '1.9.3'
7
- - '2.0.0'
8
- - '2.1.2'
9
- - jruby
10
- - rbx-2
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
11
15
  ### ALLOWED FAILURES ###
12
16
  # see how compatible we are with dev versions, but do not fail the build
13
17
  - ruby-head
14
18
  - jruby-head
15
- allow_failures:
16
- - rvm: ruby-head
17
- - rvm: jruby-head
19
+ matrix:
20
+ allow_failures:
21
+ - rvm: ruby-head
22
+ - rvm: jruby-head
@@ -1,3 +1,11 @@
1
+ ## HEAD (unreleased)
2
+
3
+ ## 2.0.0 (7th Mar 2017)
4
+
5
+ Authors: Sergey Mostovoy
6
+
7
+ * fix: logger raises exception if hash is passed as an argument to a listener
8
+
1
9
  ## 2.0.0.rc1 (17 Dec 2014)
2
10
 
3
11
  Authors: Kris Leech
@@ -6,6 +14,8 @@ Authors: Kris Leech
6
14
  * remove: rspec matcher and stubbing (moved to [wisper-rspec](https://github.com/krisleech/wisper-rspec))
7
15
  * feature: add regexp support to `on` argument
8
16
  * remove: announce alias for broadcasting
17
+ * docs: add Code of Conduct
18
+ * drop support for Ruby 1.9
9
19
 
10
20
  ## 1.6.0 (25 Oct 2014)
11
21
 
@@ -2,6 +2,10 @@
2
2
 
3
3
  We very much welcome contributions to Wisper.
4
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
+
5
9
  ## Getting started
6
10
 
7
11
  Please first check the existing [Issues](https://github.com/krisleech/wisper/issues)
@@ -19,11 +23,15 @@ Please open an issue with your proposed feature. We can discuss the feature and
19
23
  if it is acceptable we can also discuss implimentation details. You will in
20
24
  most cases have to submit a PR which adds the feature.
21
25
 
22
- We also have a [Gitter channel](https://gitter.im/krisleech/wisper).
23
-
24
26
  Wisper is a micro library and will remain lean. Some features would be most
25
27
  appropriate as an extension to Wisper.
26
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
+
27
35
  ## Questions
28
36
 
29
37
  Try the [Wiki](https://github.com/krisleech/wisper/wiki) first, the examples
@@ -33,8 +41,6 @@ Please ask questions on StackOverflow, [tagged wisper](https://stackoverflow.com
33
41
 
34
42
  Feel free to ping me the URL on [Twitter](https://twitter.com/krisleech).
35
43
 
36
- We also have a [channel on Gitter](https://gitter.im/krisleech/wisper).
37
-
38
44
  ## Pull requests
39
45
 
40
46
  * Fork the project, create a new branch from `v1` or `master`.
data/Gemfile CHANGED
@@ -3,7 +3,7 @@ source 'https://rubygems.org'
3
3
  gemspec
4
4
 
5
5
  gem 'rake', '~> 10.3.0'
6
- gem 'rspec', '~> 3.0.0'
6
+ gem 'rspec', '~> 3.4.0'
7
7
  gem 'coveralls', require: false
8
8
 
9
9
  group :extras do
data/README.md CHANGED
@@ -2,10 +2,10 @@
2
2
 
3
3
  *A micro library providing Ruby objects with Publish-Subscribe capabilities*
4
4
 
5
- [![Gem Version](https://badge.fury.io/rb/wisper.png)](http://badge.fury.io/rb/wisper)
6
- [![Code Climate](https://codeclimate.com/github/krisleech/wisper.png)](https://codeclimate.com/github/krisleech/wisper)
7
- [![Build Status](https://travis-ci.org/krisleech/wisper.png?branch=master)](https://travis-ci.org/krisleech/wisper)
8
- [![Coverage Status](https://coveralls.io/repos/krisleech/wisper/badge.png?branch=master)](https://coveralls.io/r/krisleech/wisper?branch=master)
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
9
 
10
10
  * Decouple core business logic from external concerns in Hexagonal style architectures
11
11
  * Use as an alternative to ActiveRecord callbacks and Observers in Rails apps
@@ -19,12 +19,12 @@ Note: Wisper was originally extracted from a Rails codebase but is not dependant
19
19
  Add this line to your application's Gemfile:
20
20
 
21
21
  ```ruby
22
- gem 'wisper'
22
+ gem 'wisper', '2.0.0'
23
23
  ```
24
24
 
25
25
  ## Usage
26
26
 
27
- Any class with the `Wisper::Publisher` module included can broadcast events
27
+ Any class with the `Wisper::Publisher` module included can broadcast events
28
28
  to subscribed listeners. Listeners subscribe, at runtime, to the publisher.
29
29
 
30
30
  ### Publishing
@@ -47,7 +47,7 @@ class CancelOrder
47
47
  end
48
48
  ```
49
49
 
50
- When a publisher broadcasts an event it can include number of arguments.
50
+ When a publisher broadcasts an event it can include any number of arguments.
51
51
 
52
52
  The `broadcast` method is also aliased as `publish`.
53
53
 
@@ -73,7 +73,7 @@ The listener would need to implement a method for every event it wishes to recei
73
73
  class OrderNotifier
74
74
  def cancel_order_successful(order_id)
75
75
  order = Order.find_by_id(order_id)
76
-
76
+
77
77
  # notify someone ...
78
78
  end
79
79
  end
@@ -88,10 +88,27 @@ cancel_order = CancelOrder.new
88
88
 
89
89
  cancel_order.on(:cancel_order_successful) { |order_id| ... }
90
90
  .on(:cancel_order_failed) { |order_id| ... }
91
-
91
+
92
92
  cancel_order.call(order_id)
93
93
  ```
94
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
+
95
112
  ### Handling Events Asynchronously
96
113
 
97
114
  ```ruby
@@ -100,16 +117,30 @@ cancel_order.subscribe(OrderNotifier.new, async: true)
100
117
 
101
118
  Wisper has various adapters for asynchronous event handling, please refer to
102
119
  [wisper-celluloid](https://github.com/krisleech/wisper-celluloid),
103
- [wisper-sidekiq](https://github.com/krisleech/wisper-sidekiq) or
104
- [wisper-activejob](https://github.com/krisleech/wisper-activejob).
120
+ [wisper-sidekiq](https://github.com/krisleech/wisper-sidekiq),
121
+ [wisper-activejob](https://github.com/krisleech/wisper-activejob), or
122
+ [wisper-que](https://github.com/joevandyk/wisper-que).
123
+
124
+ 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:
125
+
126
+ ```ruby
127
+ class OrderNotifier
128
+ # declare a class method if you are subscribing the listener class instead of its instance like:
129
+ # cancel_order.subscribe(OrderNotifier)
130
+ #
131
+ def self.cancel_order_successful(order_id)
132
+ order = Order.find_by_id(order_id)
105
133
 
106
- Depending on the adapter used the listener may need to be a class instead of an object.
134
+ # notify someone ...
135
+ end
136
+ end
137
+ ```
107
138
 
108
139
  ### ActionController
109
140
 
110
141
  ```ruby
111
142
  class CancelOrderController < ApplicationController
112
-
143
+
113
144
  def create
114
145
  cancel_order = CancelOrder.new
115
146
 
@@ -132,7 +163,7 @@ If you wish to publish directly from ActiveRecord models you can broadcast event
132
163
  ```ruby
133
164
  class Order < ActiveRecord::Base
134
165
  include Wisper::Publisher
135
-
166
+
136
167
  after_commit :publish_creation_successful, on: :create
137
168
  after_validation :publish_creation_failed, on: :create
138
169
 
@@ -171,9 +202,12 @@ class.
171
202
 
172
203
  ```ruby
173
204
  Wisper.subscribe(MyListener.new, scope: :MyPublisher)
205
+ Wisper.subscribe(MyListener.new, scope: MyPublisher)
206
+ Wisper.subscribe(MyListener.new, scope: "MyPublisher")
207
+ Wisper.subscribe(MyListener.new, scope: [:MyPublisher, :MyOtherPublisher])
174
208
  ```
175
209
 
176
- This will subscribe the listener to all instances of `MyPublisher` and its
210
+ This will subscribe the listener to all instances of the specified class(es) and their
177
211
  subclasses.
178
212
 
179
213
  Alternatively you can also do exactly the same with a publisher class itself:
@@ -193,7 +227,7 @@ end
193
227
  ```
194
228
 
195
229
  Any events broadcast within the block by any publisher will be sent to the
196
- listeners.
230
+ listeners.
197
231
 
198
232
  This is useful for capturing events published by objects to which you do not have access in a given context.
199
233
 
@@ -202,11 +236,11 @@ Temporary Global Listeners are threadsafe.
202
236
  ## Subscribing to selected events
203
237
 
204
238
  By default a listener will get notified of all events it can respond to. You
205
- can limit which events a listener is notified of by passing an string, symbol,
239
+ can limit which events a listener is notified of by passing a string, symbol,
206
240
  array or regular expression to `on`:
207
241
 
208
242
  ```ruby
209
- post_creater.subscribe(PusherListener.new, on: :create_post_successful)
243
+ post_creator.subscribe(PusherListener.new, on: :create_post_successful)
210
244
  ```
211
245
 
212
246
  ## Prefixing broadcast events
@@ -215,10 +249,10 @@ If you would prefer listeners to receive events with a prefix, for example
215
249
  `on`, you can do so by passing a string or symbol to `prefix:`.
216
250
 
217
251
  ```ruby
218
- post_creater.subscribe(PusherListener.new, prefix: :on)
252
+ post_creator.subscribe(PusherListener.new, prefix: :on)
219
253
  ```
220
254
 
221
- If `post_creater` where to broadcast the event `post_created` the subscribed
255
+ If `post_creator` were to broadcast the event `post_created` the subscribed
222
256
  listeners would receive `on_post_created`. You can also pass `true` which will
223
257
  use the default prefix, "on".
224
258
 
@@ -231,7 +265,7 @@ broadcast. However it can be mapped to a different method using `with:`.
231
265
  report_creator.subscribe(MailResponder.new, with: :successful)
232
266
  ```
233
267
 
234
- This is pretty useless unless used in conjuction with `on:`, since all events
268
+ This is pretty useless unless used in conjunction with `on:`, since all events
235
269
  will get mapped to `:successful`. Instead you might do something like this:
236
270
 
237
271
  ```ruby
@@ -255,11 +289,14 @@ report_creator.subscribe(MailResponder.new, on: :create_report_failed,
255
289
  You could also alias the method within your listener, as such
256
290
  `alias successful create_report_successful`.
257
291
 
258
- ## RSpec
292
+ ## Testing
293
+
294
+ Testing matchers and stubs are in seperate gems.
259
295
 
260
- Please see [wisper-rspec](https://github.com/krisleech/wisper-rspec).
296
+ * [wisper-rspec](https://github.com/krisleech/wisper-rspec)
297
+ * [wisper-minitest](https://github.com/digitalcuisine/wisper-minitest)
261
298
 
262
- ## Clearing Global Listeners
299
+ ### Clearing Global Listeners
263
300
 
264
301
  If you use global listeners in non-feature tests you _might_ want to clear them
265
302
  in a hook to prevent global subscriptions persisting between tests.
@@ -268,21 +305,40 @@ in a hook to prevent global subscriptions persisting between tests.
268
305
  after { Wisper.clear }
269
306
  ```
270
307
 
308
+ ## Need help?
309
+
310
+ The [Wiki](https://github.com/krisleech/wisper/wiki) has more examples,
311
+ articles and talks.
312
+
313
+ Got a specific question, try the
314
+ [Wisper tag on StackOverflow](http://stackoverflow.com/questions/tagged/wisper).
315
+
271
316
  ## Compatibility
272
317
 
273
- Tested with MRI 1.9.x, MRI 2.0.0, JRuby (1.9 and 2.0 mode) and Rubinius (1.9
274
- mode).
318
+ Tested with MRI 2.x, JRuby and Rubinius.
275
319
 
276
320
  See the [build status](https://travis-ci.org/krisleech/wisper) for details.
277
321
 
278
322
  ## Running Specs
279
323
 
280
324
  ```
281
- rspec spec
325
+ bundle exec rspec
326
+ ```
327
+
328
+ To run the specs on code changes try [entr](http://entrproject.org/):
329
+
330
+ ```
331
+ ls **/*.rb | entr bundle exec rspec
282
332
  ```
283
333
 
284
- There is both a `Rakefile` and `Guardfile`, if you like you prefer to run the
285
- specs using `guard-rspec` or `rake`.
334
+ ## Contributing
335
+
336
+ Please read the [Contributing Guidelines](https://github.com/krisleech/wisper/blob/master/CONTRIBUTING.md).
337
+
338
+ ## Security
339
+
340
+ * gem releases are [signed](http://guides.rubygems.org/security/) ([public key](https://github.com/krisleech/wisper/blob/master/gem-public_cert.pem))
341
+ * commits are GPG signed ([public key](https://pgp.mit.edu/pks/lookup?op=get&search=0x3ABC74851F7CCC88))
286
342
 
287
343
  ## License
288
344
 
@@ -2,6 +2,8 @@ require 'set'
2
2
  require 'wisper/version'
3
3
  require 'wisper/configuration'
4
4
  require 'wisper/publisher'
5
+ require 'wisper/value_objects/prefix'
6
+ require 'wisper/value_objects/events'
5
7
  require 'wisper/registration/registration'
6
8
  require 'wisper/registration/object'
7
9
  require 'wisper/registration/block'
@@ -33,6 +35,10 @@ module Wisper
33
35
  end
34
36
  end
35
37
 
38
+ def self.unsubscribe(*listeners)
39
+ GlobalListeners.unsubscribe(*listeners)
40
+ end
41
+
36
42
  def self.publisher
37
43
  Publisher
38
44
  end
@@ -9,22 +9,28 @@ module Wisper
9
9
  end
10
10
 
11
11
  def broadcast(listener, publisher, event, args)
12
- @logger.info("[WISPER] #{name(publisher)} published #{event} to #{name(listener)} with #{arg_names(args)}")
12
+ @logger.info("[WISPER] #{name(publisher)} published #{event} to #{name(listener)} with #{args_info(args)}")
13
13
  @broadcaster.broadcast(listener, publisher, event, args)
14
14
  end
15
15
 
16
16
  private
17
17
 
18
18
  def name(object)
19
- id_method = %w(id uuid key object_id).find { |id_method| object.respond_to?(id_method) }
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
20
22
  id = object.send(id_method)
21
23
  class_name = object.class == Class ? object.name : object.class.name
22
24
  "#{class_name}##{id}"
23
25
  end
24
26
 
25
- def arg_names(args)
27
+ def args_info(args)
26
28
  return 'no arguments' if args.empty?
27
- args.map { |arg| name(arg) }.join(', ')
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(', ')
28
34
  end
29
35
  end
30
36
  end
@@ -17,10 +17,19 @@ module Wisper
17
17
  self
18
18
  end
19
19
 
20
+ # sets the default value for prefixes
21
+ #
22
+ # @param [#to_s] value
23
+ #
24
+ # @return [String]
25
+ def default_prefix=(value)
26
+ ValueObjects::Prefix.default = value
27
+ end
28
+
20
29
  class Broadcasters
21
30
  extend Forwardable
22
31
 
23
- def_delegators :@data, :fetch, :[], :[]=, :empty?, :include?, :clear
32
+ def_delegators :@data, :[], :[]=, :empty?, :include?, :clear, :keys, :to_h
24
33
 
25
34
  def initialize
26
35
  @data = {}
@@ -24,6 +24,15 @@ module Wisper
24
24
  self
25
25
  end
26
26
 
27
+ def unsubscribe(*listeners)
28
+ with_mutex do
29
+ @registrations.delete_if do |registration|
30
+ listeners.include?(registration.listener)
31
+ end
32
+ end
33
+ self
34
+ end
35
+
27
36
  def registrations
28
37
  with_mutex { @registrations }
29
38
  end
@@ -40,6 +49,10 @@ module Wisper
40
49
  instance.subscribe(*listeners)
41
50
  end
42
51
 
52
+ def self.unsubscribe(*listeners)
53
+ instance.unsubscribe(*listeners)
54
+ end
55
+
43
56
  def self.registrations
44
57
  instance.registrations
45
58
  end
@@ -11,6 +11,7 @@ module Wisper
11
11
  #
12
12
  # @return [self]
13
13
  def subscribe(listener, options = {})
14
+ raise ArgumentError, "#{__method__} does not take a block, did you mean to call #on instead?" if block_given?
14
15
  local_registrations << ObjectRegistration.new(listener, options)
15
16
  self
16
17
  end
@@ -23,6 +24,7 @@ module Wisper
23
24
  # @return [self]
24
25
  def on(*events, &block)
25
26
  raise ArgumentError, 'must give at least one event' if events.empty?
27
+ raise ArgumentError, 'must pass a block' if !block
26
28
  local_registrations << BlockRegistration.new(block, on: events)
27
29
  self
28
30
  end
@@ -7,7 +7,7 @@ module Wisper
7
7
  def initialize(listener, options)
8
8
  super(listener, options)
9
9
  @with = options[:with]
10
- @prefix = stringify_prefix(options[:prefix])
10
+ @prefix = ValueObjects::Prefix.new options[:prefix]
11
11
  @allowed_classes = Array(options[:scope]).map(&:to_s).to_set
12
12
  @broadcaster = map_broadcaster(options[:async] || options[:broadcaster])
13
13
  end
@@ -29,21 +29,6 @@ module Wisper
29
29
  prefix + (with || event).to_s
30
30
  end
31
31
 
32
- def stringify_prefix(_prefix)
33
- case _prefix
34
- when nil
35
- ''
36
- when true
37
- default_prefix + '_'
38
- else
39
- _prefix.to_s + '_'
40
- end
41
- end
42
-
43
- def default_prefix
44
- 'on'
45
- end
46
-
47
32
  def map_broadcaster(value)
48
33
  return value if value.respond_to?(:broadcast)
49
34
  value = :async if value == true
@@ -4,39 +4,15 @@ module Wisper
4
4
  class Registration
5
5
  attr_reader :on, :listener
6
6
 
7
- ALL = Object.new.freeze
8
-
9
7
  def initialize(listener, options)
10
8
  @listener = listener
11
- @on = stringify(options.fetch(:on, ALL))
9
+ @on = ValueObjects::Events.new options[:on]
12
10
  end
13
11
 
14
12
  private
15
13
 
16
14
  def should_broadcast?(event)
17
- return true if on == ALL
18
-
19
- case on.class.name
20
- when 'String'
21
- event == on
22
- when 'Array'
23
- on.include?(event)
24
- when 'Regexp'
25
- !!on.match(event)
26
- else
27
- raise ArgumentError, "#{on.class} not supported for `on` argument"
28
- end
29
- end
30
-
31
- def stringify(on)
32
- case on.class.name
33
- when 'Symbol'
34
- on.to_s
35
- when 'Array'
36
- on.map(&:to_s)
37
- else
38
- on
39
- end
15
+ on.include? event
40
16
  end
41
17
  end
42
18
  end
@@ -0,0 +1,61 @@
1
+ module Wisper
2
+ module ValueObjects #:nodoc:
3
+ # Describes allowed events
4
+ #
5
+ # Duck-types the argument to quack like array of strings
6
+ # when responding to the {#include?} method call.
7
+ class Events
8
+
9
+ # @!scope class
10
+ # @!method new(on)
11
+ # Initializes a 'list' of events
12
+ #
13
+ # @param [NilClass, String, Symbol, Array, Regexp] list
14
+ #
15
+ # @raise [ArgumentError]
16
+ # if an argument if of unsupported type
17
+ #
18
+ # @return [undefined]
19
+ def initialize(list)
20
+ @list = list
21
+ end
22
+
23
+ # Check if given event is 'included' to the 'list' of events
24
+ #
25
+ # @param [#to_s] event
26
+ #
27
+ # @return [Boolean]
28
+ def include?(event)
29
+ appropriate_method.call(event.to_s)
30
+ end
31
+
32
+ private
33
+
34
+ def methods
35
+ {
36
+ NilClass => ->(_event) { true },
37
+ String => ->(event) { list == event },
38
+ Symbol => ->(event) { list.to_s == event },
39
+ Enumerable => ->(event) { list.map(&:to_s).include? event },
40
+ Regexp => ->(event) { list.match(event) || false }
41
+ }
42
+ end
43
+
44
+ def list
45
+ @list
46
+ end
47
+
48
+ def appropriate_method
49
+ @appropriate_method ||= methods[recognized_type]
50
+ end
51
+
52
+ def recognized_type
53
+ methods.keys.detect(&list.method(:is_a?)) || type_not_recognized
54
+ end
55
+
56
+ def type_not_recognized
57
+ fail(ArgumentError, "#{list.class} not supported for `on` argument")
58
+ end
59
+ end # class Events
60
+ end # module ValueObjects
61
+ end # module Wisper
@@ -0,0 +1,29 @@
1
+ module Wisper
2
+ module ValueObjects #:nodoc:
3
+ # Prefix for notifications
4
+ #
5
+ # @example
6
+ # Wisper::ValueObjects::Prefix.new nil # => ""
7
+ # Wisper::ValueObjects::Prefix.new "when" # => "when_"
8
+ # Wisper::ValueObjects::Prefix.new true # => "on_"
9
+ class Prefix < String
10
+ class << self
11
+ attr_accessor :default
12
+ end
13
+
14
+ # @param [true, nil, #to_s] value
15
+ #
16
+ # @return [undefined]
17
+ def initialize(value = nil)
18
+ super "#{ (value == true) ? default : value }_"
19
+ replace "" if self == "_"
20
+ end
21
+
22
+ private
23
+
24
+ def default
25
+ self.class.default || 'on'
26
+ end
27
+ end # class Prefix
28
+ end # module ValueObjects
29
+ end # module Wisper
@@ -1,3 +1,3 @@
1
1
  module Wisper
2
- VERSION = "2.0.0.rc1"
2
+ VERSION = "2.0.0"
3
3
  end
@@ -1,7 +1,8 @@
1
1
  describe Wisper::TemporaryListeners do
2
2
  let(:listener_1) { double('listener', :to_a => nil) } # [1]
3
3
  let(:listener_2) { double('listener', :to_a => nil) }
4
- let(:publisher) { Object.class_eval { include Wisper::Publisher } }
4
+
5
+ let(:publisher) { publisher_class.new }
5
6
 
6
7
  describe '.subscribe' do
7
8
  it 'globally subscribes listener for duration of given block' do
@@ -31,30 +32,32 @@ describe Wisper::TemporaryListeners do
31
32
  publisher.instance_eval { broadcast(:failure) }
32
33
  end
33
34
 
34
- it 'ensures registrations are thread local' do
35
+ it 'is thread safe' do
35
36
  num_threads = 20
36
37
  (1..num_threads).to_a.map do
37
38
  Thread.new do
38
39
  Wisper::TemporaryListeners.registrations << Object.new
39
- expect(Wisper::TemporaryListeners.registrations.size).to eql 1
40
+ expect(Wisper::TemporaryListeners.registrations.size).to eq 1
40
41
  end
41
42
  end.each(&:join)
42
43
 
43
- expect(Wisper::TemporaryListeners.registrations.size).to eql 0
44
+ expect(Wisper::TemporaryListeners.registrations).to be_empty
44
45
  end
45
46
 
46
- it 'ensures registrations are cleared after exception raised in block' do
47
+ it 'clears registrations when an exception occurs' do
48
+ MyError = Class.new(StandardError)
49
+
47
50
  begin
48
51
  Wisper::TemporaryListeners.subscribe(listener_1) do
49
- raise StandardError
52
+ raise MyError
50
53
  end
51
- rescue StandardError
54
+ rescue MyError
52
55
  end
53
56
 
54
- expect(Wisper::TemporaryListeners.registrations.size).to eql 0
57
+ expect(Wisper::TemporaryListeners.registrations).to be_empty
55
58
  end
56
59
 
57
- it 'returns self so methods can be chained' do
60
+ it 'returns self' do
58
61
  expect(Wisper::TemporaryListeners.subscribe {}).to be_an_instance_of(Wisper::TemporaryListeners)
59
62
  end
60
63
  end
@@ -28,12 +28,12 @@ module Wisper
28
28
  context 'without arguments' do
29
29
  let(:args) { [] }
30
30
 
31
- it 'logs publised event' do
31
+ it 'logs published event' do
32
32
  expect(logger).to receive(:info).with('[WISPER] Publisher#1 published thing_created to Listener#2 with no arguments')
33
33
  subject.broadcast(listener, publisher, event, args)
34
34
  end
35
35
 
36
- it 'delgates broadcast to given broadcaster' do
36
+ it 'delegates broadcast to a given broadcaster' do
37
37
  expect(broadcaster).to receive(:broadcast).with(listener, publisher, event, args)
38
38
  subject.broadcast(listener, publisher, event, args)
39
39
  end
@@ -47,10 +47,30 @@ module Wisper
47
47
  subject.broadcast(listener, publisher, event, args)
48
48
  end
49
49
 
50
- it 'delgates broadcast to given broadcaster' do
50
+ it 'delegates broadcast to a given broadcaster' do
51
51
  expect(broadcaster).to receive(:broadcast).with(listener, publisher, event, args)
52
52
  subject.broadcast(listener, publisher, event, args)
53
53
  end
54
+
55
+ context 'when argument is a hash' do
56
+ let(:args) { [hash] }
57
+ let(:hash) { {key: 'value'} }
58
+
59
+ it 'logs published event and arguments' do
60
+ expect(logger).to receive(:info).with("[WISPER] Publisher#1 published thing_created to Listener#2 with Hash##{hash.object_id}: #{hash.inspect}")
61
+ subject.broadcast(listener, publisher, event, args)
62
+ end
63
+ end
64
+
65
+ context 'when argument is an integer' do
66
+ let(:args) { [number] }
67
+ let(:number) { 10 }
68
+
69
+ it 'logs published event and arguments' do
70
+ expect(logger).to receive(:info).with("[WISPER] Publisher#1 published thing_created to Listener#2 with #{number.class.name}##{number.object_id}: 10")
71
+ subject.broadcast(listener, publisher, event, args)
72
+ end
73
+ end
54
74
  end
55
75
 
56
76
  end
@@ -0,0 +1,11 @@
1
+ module Wisper
2
+ describe Configuration::Broadcasters do
3
+ describe 'broadcasters' do
4
+ describe '#to_h' do
5
+ it 'returns a Hash' do
6
+ expect(subject.to_h).to be_instance_of(Hash)
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -20,5 +20,17 @@ module Wisper
20
20
  end
21
21
  end
22
22
  end
23
+
24
+ describe '#default_prefix=' do
25
+ let(:prefix_class) { ValueObjects::Prefix }
26
+ let(:default_value) { double }
27
+
28
+ before { allow(prefix_class).to receive(:default=) }
29
+
30
+ it 'sets the default value for prefixes' do
31
+ expect(prefix_class).to receive(:default=).with(default_value)
32
+ subject.default_prefix = default_value
33
+ end
34
+ end
23
35
  end
24
36
  end
@@ -211,6 +211,15 @@ describe Wisper::Publisher do
211
211
  it 'is aliased to .subscribe' do
212
212
  expect(publisher).to respond_to(:subscribe)
213
213
  end
214
+
215
+ it 'raises a helpful error if trying to pass a block' do
216
+ invalid = ->{
217
+ publisher.subscribe(:success) do
218
+ puts
219
+ end
220
+ }
221
+ expect{ invalid.call }.to raise_error(ArgumentError)
222
+ end
214
223
  end
215
224
 
216
225
  describe '.on' do
@@ -222,6 +231,10 @@ describe Wisper::Publisher do
222
231
  expect { publisher.on() {} }.to raise_error(ArgumentError)
223
232
  end
224
233
 
234
+ it 'raises an error of no block given' do
235
+ expect { publisher.on(:something) }.to raise_error(ArgumentError)
236
+ end
237
+
225
238
  it 'returns publisher so methods can be chained' do
226
239
  expect(publisher.on(:foo) {}).to eq publisher
227
240
  end
@@ -0,0 +1,107 @@
1
+ describe Wisper::ValueObjects::Events do
2
+ context 'nil' do
3
+ subject { described_class.new nil }
4
+
5
+ describe '#include?' do
6
+ it 'returns true' do
7
+ expect(subject.include? 'foo').to be_truthy
8
+ expect(subject.include? :bar).to be_truthy
9
+ end
10
+ end
11
+ end
12
+
13
+ context '"foo"' do
14
+ let(:foo) { Class.new(String).new 'foo' }
15
+ subject { described_class.new foo }
16
+
17
+ describe '#include?' do
18
+ it 'returns true for "foo"' do
19
+ expect(subject.include? 'foo').to be_truthy
20
+ end
21
+
22
+ it 'returns true for :foo' do
23
+ expect(subject.include? :foo).to be_truthy
24
+ end
25
+
26
+ it 'returns false otherwise' do
27
+ expect(subject.include? 'bar').to be_falsey
28
+ expect(subject.include? :bar).to be_falsey
29
+ end
30
+ end
31
+ end
32
+
33
+ context ':foo' do
34
+ subject { described_class.new :foo }
35
+
36
+ describe '#include?' do
37
+ it 'returns true for "foo"' do
38
+ expect(subject.include? 'foo').to be_truthy
39
+ end
40
+
41
+ it 'returns true for :foo' do
42
+ expect(subject.include? :foo).to be_truthy
43
+ end
44
+
45
+ it 'returns false otherwise' do
46
+ expect(subject.include? 'bar').to be_falsey
47
+ expect(subject.include? :bar).to be_falsey
48
+ end
49
+ end
50
+ end
51
+
52
+ context '[:foo, "bar"]' do
53
+ subject { described_class.new [:foo, 'bar'] }
54
+
55
+ describe '#include?' do
56
+ it 'returns true for "foo"' do
57
+ expect(subject.include? 'foo').to be_truthy
58
+ end
59
+
60
+ it 'returns true for :foo' do
61
+ expect(subject.include? :foo).to be_truthy
62
+ end
63
+
64
+ it 'returns true for "bar"' do
65
+ expect(subject.include? 'bar').to be_truthy
66
+ end
67
+
68
+ it 'returns true for :bar' do
69
+ expect(subject.include? :bar).to be_truthy
70
+ end
71
+
72
+ it 'returns false otherwise' do
73
+ expect(subject.include? 'baz').to be_falsey
74
+ expect(subject.include? :baz).to be_falsey
75
+ end
76
+ end
77
+ end
78
+
79
+ context 'by /foo/' do
80
+ subject { described_class.new(/foo/) }
81
+
82
+ describe '#include?' do
83
+ it 'returns true for "foo"' do
84
+ expect(subject.include? 'foo').to be_truthy
85
+ end
86
+
87
+ it 'returns true for :foo' do
88
+ expect(subject.include? :foo).to be_truthy
89
+ end
90
+
91
+ it 'returns false otherwise' do
92
+ expect(subject.include? 'bar').to be_falsey
93
+ expect(subject.include? :bar).to be_falsey
94
+ end
95
+ end
96
+ end
97
+
98
+ context 'another class' do
99
+ subject { described_class.new Object.new }
100
+
101
+ describe '#include?' do
102
+ it 'raises ArgumentError' do
103
+ expect { subject.include? 'foo' }.to raise_error(ArgumentError)
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,46 @@
1
+ describe Wisper::ValueObjects::Prefix do
2
+
3
+ it 'is a string' do
4
+ expect(subject).to be_kind_of String
5
+ end
6
+
7
+ describe '.new' do
8
+ context 'without arguments' do
9
+ subject { described_class.new }
10
+ it { is_expected.to eq '' }
11
+ end
12
+
13
+ context 'nil' do
14
+ subject { described_class.new nil }
15
+ it { is_expected.to eq '' }
16
+ end
17
+
18
+ context 'true' do
19
+ subject { described_class.new true }
20
+ it { is_expected.to eq 'on_' }
21
+ end
22
+
23
+ context '"foo"' do
24
+ subject { described_class.new 'foo' }
25
+ it { is_expected.to eq 'foo_' }
26
+ end
27
+ end
28
+
29
+ describe '.default=' do
30
+ after { described_class.default = nil }
31
+
32
+ context 'nil' do
33
+ it "doesn't change default prefix" do
34
+ expect { described_class.default = nil }
35
+ .not_to change { described_class.new true }.from('on_')
36
+ end
37
+ end
38
+
39
+ context '"foo"' do
40
+ it 'changes default prefix' do
41
+ expect { described_class.default = 'foo' }
42
+ .to change { described_class.new true }.from('on_').to('foo_')
43
+ end
44
+ end
45
+ end
46
+ end
@@ -1,62 +1,99 @@
1
1
  describe Wisper do
2
2
  describe '.subscribe' do
3
- context 'given block' do
3
+ context 'when given block' do
4
+
4
5
  it 'subscribes listeners to all events for duration of the block' do
5
6
  publisher = publisher_class.new
6
- listener = double('listener')
7
+ listener = double('listener')
7
8
 
8
- expect(listener).to receive(:im_here)
9
- expect(listener).not_to receive(:not_here)
9
+ expect(listener).to receive(:first_event)
10
+ expect(listener).not_to receive(:second_event)
10
11
 
11
12
  Wisper.subscribe(listener) do
12
- publisher.send(:broadcast, 'im_here')
13
+ publisher.send(:broadcast, 'first_event')
13
14
  end
14
15
 
15
- publisher.send(:broadcast, 'not_here')
16
+ publisher.send(:broadcast, 'second_event')
16
17
  end
17
18
  end
18
19
 
19
- context 'no block given' do
20
- it 'subscribes a listener to all events' do
20
+ context 'when no block given' do
21
+ it 'subscribes listener to all events' do
21
22
  listener = double('listener')
22
23
  Wisper.subscribe(listener)
23
24
  expect(Wisper::GlobalListeners.listeners).to eq [listener]
24
25
  end
25
26
 
26
- it 'subscribes multiple listeners to all events' do
27
+ it 'subscribes listeners to all events' do
27
28
  listener_1 = double('listener')
28
29
  listener_2 = double('listener')
29
- listener_3 = double('listener')
30
30
 
31
31
  Wisper.subscribe(listener_1, listener_2)
32
32
 
33
33
  expect(Wisper::GlobalListeners.listeners).to include listener_1, listener_2
34
- expect(Wisper::GlobalListeners.listeners).not_to include listener_3
35
34
  end
36
35
  end
37
36
  end
38
37
 
39
- it '.publisher returns the Publisher module' do
40
- expect(Wisper.publisher).to eq Wisper::Publisher
38
+ describe '.unsubscribe' do
39
+ it 'removes listener from list of listeners' do
40
+ listener = double('listener')
41
+
42
+ Wisper.subscribe(listener)
43
+ expect(Wisper::GlobalListeners.listeners).to eq [listener]
44
+
45
+ Wisper.unsubscribe(listener)
46
+ expect(Wisper::GlobalListeners.listeners).to eq []
47
+ end
48
+
49
+ it 'removes listeners from list of listeners' do
50
+ listener_1 = double('listener')
51
+ listener_2 = double('listener')
52
+
53
+ Wisper.subscribe(listener_1, listener_2)
54
+ expect(Wisper::GlobalListeners.listeners).to include listener_1, listener_2
55
+
56
+ Wisper.unsubscribe(listener_1, listener_2)
57
+ expect(Wisper::GlobalListeners.listeners).to eq []
58
+ end
41
59
  end
42
60
 
43
- it '.clear clears all global listeners' do
44
- 10.times { Wisper.subscribe(double) }
45
- Wisper.clear
46
- expect(Wisper::GlobalListeners.listeners).to be_empty
61
+ describe '.publisher' do
62
+ it 'returns the Publisher module' do
63
+ expect(Wisper.publisher).to eq Wisper::Publisher
64
+ end
47
65
  end
48
66
 
49
- it '.configuration returns configuration' do
50
- expect(Wisper.configuration).to be_an_instance_of(Wisper::Configuration)
67
+ describe '.clear' do
68
+ before { Wisper.subscribe(double) }
69
+
70
+ it 'clears all global listeners' do
71
+ Wisper.clear
72
+ expect(Wisper::GlobalListeners.listeners).to be_empty
73
+ end
51
74
  end
52
75
 
53
- it '.configure yields block to configuration' do
54
- Wisper.configure do |config|
55
- expect(config).to be_an_instance_of(Wisper::Configuration)
76
+ describe '.configuration' do
77
+ it 'returns configuration object' do
78
+ expect(Wisper.configuration).to be_an_instance_of(Wisper::Configuration)
79
+ end
80
+
81
+ it 'is memorized' do
82
+ expect(Wisper.configuration).to eq Wisper.configuration
56
83
  end
57
84
  end
58
85
 
59
- it 'has a default broadcaster' do
60
- expect(Wisper.configuration.broadcasters[:default]).to be_instance_of(Wisper::Broadcasters::SendBroadcaster)
86
+ describe '.configure' do
87
+ it 'passes configuration to given block' do
88
+ Wisper.configure do |config|
89
+ expect(config).to be_an_instance_of(Wisper::Configuration)
90
+ end
91
+ end
92
+ end
93
+
94
+ describe '.setup' do
95
+ it 'sets a default broadcaster' do
96
+ expect(Wisper.configuration.broadcasters[:default]).to be_instance_of(Wisper::Broadcasters::SendBroadcaster)
97
+ end
61
98
  end
62
99
  end
@@ -22,11 +22,3 @@ end
22
22
  def publisher_class
23
23
  Class.new { include Wisper::Publisher }
24
24
  end
25
-
26
- # prevents deprecation warning showing up in spec output
27
- def silence_warnings
28
- original_verbosity = $VERBOSE
29
- $VERBOSE = nil
30
- yield
31
- $VERBOSE = original_verbosity
32
- end
@@ -8,8 +8,12 @@ Gem::Specification.new do |gem|
8
8
  gem.version = Wisper::VERSION
9
9
  gem.authors = ["Kris Leech"]
10
10
  gem.email = ["kris.leech@gmail.com"]
11
- gem.description = %q{pub/sub for Ruby objects}
12
- gem.summary = %q{pub/sub for Ruby objects}
11
+ gem.description = <<-DESC
12
+ A micro library providing objects with Publish-Subscribe capabilities.
13
+ Both synchronous (in-process) and asynchronous (out-of-process) subscriptions are supported.
14
+ Check out the Wiki for articles, guides and examples: https://github.com/krisleech/wisper/wiki
15
+ DESC
16
+ gem.summary = "A micro library providing objects with Publish-Subscribe capabilities"
13
17
  gem.homepage = "https://github.com/krisleech/wisper"
14
18
  gem.license = "MIT"
15
19
 
metadata CHANGED
@@ -1,38 +1,19 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wisper
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.rc1
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kris Leech
8
8
  autorequire:
9
9
  bindir: bin
10
- cert_chain:
11
- - |
12
- -----BEGIN CERTIFICATE-----
13
- MIIDeDCCAmCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBBMRMwEQYDVQQDDAprcmlz
14
- LmxlZWNoMRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJk/IsZAEZFgNj
15
- b20wHhcNMTQxMTA1MTEwMzQ4WhcNMTUxMTA1MTEwMzQ4WjBBMRMwEQYDVQQDDApr
16
- cmlzLmxlZWNoMRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJk/IsZAEZ
17
- FgNjb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtW0/UtrFK/tSm
18
- uq5HnCUkZAQjnSaZ/h1Tby9s30CDJjDUdizPRdLQCplLDAMHFsAfTyD0Mc+Ez8o9
19
- CdTh8EZ4TSf+nokL+SUprpdR6qm6OWU03Ntd+bDCP0+rdqCX82g3N3mnvjR9aD3a
20
- +hd9Fhp0WuEyqTNjQ7IlopeUPDW7eYfSwI4bjfRHxsDR1GuZ3j0npxCAgAIN41WH
21
- MSTTZhdo0vKEiKZEtMMnT6w6fG/c3XIhVVPGnqy5+IZqBL0SYC+WJL3vC6yUBgqB
22
- nrpA/q+b3M69W+q+TkGv0qOnrxln0O7J2pykjoGIxUhhRkiGEldEhy9dxQWubffr
23
- hVJ4F0wLAgMBAAGjezB5MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQW
24
- BBSzq+x8mwj0ldvNkvjOl44OJG354jAfBgNVHREEGDAWgRRrcmlzLmxlZWNoQGdt
25
- YWlsLmNvbTAfBgNVHRIEGDAWgRRrcmlzLmxlZWNoQGdtYWlsLmNvbTANBgkqhkiG
26
- 9w0BAQUFAAOCAQEAF5M2Md3DcNCrQrDRDLaIzHaMM+RTgfbpgmZ6tU0iEowES18g
27
- QWQgrAbFuvQRPETJ2gbL5AC35fEqN80nU+3GhgW/bDYhII5D3PGLMorxhFw1JYLI
28
- 0Fd7MCE0sImc2rPybYUdpZ6TxvqgPKp+8CzM8vBUrdYd+dSHXit1piViWBcZcJb+
29
- EL5Ze4IodjkCPAeHvu2MQieieViLyfB4eG1syvfkxvAXCjFHeQoIFP16vVtcljdF
30
- k5cHH/4SGeMuGrSLRsqVvltxVV3AbQAfH8WUos2brjYHsoH5tVPrJ7UcFhzP95oU
31
- pEfFMW42smiNTOXpzG6JoIpA11szEHFT5ZS+UQ==
32
- -----END CERTIFICATE-----
33
- date: 2014-12-17 00:00:00.000000000 Z
10
+ cert_chain: []
11
+ date: 2017-03-07 00:00:00.000000000 Z
34
12
  dependencies: []
35
- description: pub/sub for Ruby objects
13
+ description: |2
14
+ A micro library providing objects with Publish-Subscribe capabilities.
15
+ Both synchronous (in-process) and asynchronous (out-of-process) subscriptions are supported.
16
+ Check out the Wiki for articles, guides and examples: https://github.com/krisleech/wisper/wiki
36
17
  email:
37
18
  - kris.leech@gmail.com
38
19
  executables: []
@@ -45,7 +26,6 @@ files:
45
26
  - CHANGELOG.md
46
27
  - CONTRIBUTING.md
47
28
  - Gemfile
48
- - Guardfile
49
29
  - README.md
50
30
  - Rakefile
51
31
  - gem-public_cert.pem
@@ -59,6 +39,8 @@ files:
59
39
  - lib/wisper/registration/object.rb
60
40
  - lib/wisper/registration/registration.rb
61
41
  - lib/wisper/temporary_listeners.rb
42
+ - lib/wisper/value_objects/events.rb
43
+ - lib/wisper/value_objects/prefix.rb
62
44
  - lib/wisper/version.rb
63
45
  - spec/lib/global_listeners_spec.rb
64
46
  - spec/lib/integration_spec.rb
@@ -66,9 +48,12 @@ files:
66
48
  - spec/lib/temporary_global_listeners_spec.rb
67
49
  - spec/lib/wisper/broadcasters/logger_broadcaster_spec.rb
68
50
  - spec/lib/wisper/broadcasters/send_broadcaster_spec.rb
51
+ - spec/lib/wisper/configuration/broadcasters_spec.rb
69
52
  - spec/lib/wisper/configuration_spec.rb
70
53
  - spec/lib/wisper/publisher_spec.rb
71
54
  - spec/lib/wisper/registrations/object_spec.rb
55
+ - spec/lib/wisper/value_objects/events_spec.rb
56
+ - spec/lib/wisper/value_objects/prefix_spec.rb
72
57
  - spec/lib/wisper_spec.rb
73
58
  - spec/spec_helper.rb
74
59
  - wisper.gemspec
@@ -87,15 +72,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
87
72
  version: '0'
88
73
  required_rubygems_version: !ruby/object:Gem::Requirement
89
74
  requirements:
90
- - - ">"
75
+ - - ">="
91
76
  - !ruby/object:Gem::Version
92
- version: 1.3.1
77
+ version: '0'
93
78
  requirements: []
94
79
  rubyforge_project:
95
- rubygems_version: 2.2.2
80
+ rubygems_version: 2.5.1
96
81
  signing_key:
97
82
  specification_version: 4
98
- summary: pub/sub for Ruby objects
83
+ summary: A micro library providing objects with Publish-Subscribe capabilities
99
84
  test_files:
100
85
  - spec/lib/global_listeners_spec.rb
101
86
  - spec/lib/integration_spec.rb
@@ -103,9 +88,11 @@ test_files:
103
88
  - spec/lib/temporary_global_listeners_spec.rb
104
89
  - spec/lib/wisper/broadcasters/logger_broadcaster_spec.rb
105
90
  - spec/lib/wisper/broadcasters/send_broadcaster_spec.rb
91
+ - spec/lib/wisper/configuration/broadcasters_spec.rb
106
92
  - spec/lib/wisper/configuration_spec.rb
107
93
  - spec/lib/wisper/publisher_spec.rb
108
94
  - spec/lib/wisper/registrations/object_spec.rb
95
+ - spec/lib/wisper/value_objects/events_spec.rb
96
+ - spec/lib/wisper/value_objects/prefix_spec.rb
109
97
  - spec/lib/wisper_spec.rb
110
98
  - spec/spec_helper.rb
111
- has_rdoc:
@@ -1,2 +0,0 @@
1
- e�I�fwh��~�PDnZ��/Me��n�j@����Zu$�������'�������)��3�X�k��L���K�4�?B���t7D{��8٭�;�¦�d��m�s@� �!�^*���̊�ǒ����>��3w`��V�Ms���ԙ�$����C�% �
2
- >q��̺��~��]�E+�� /g�&����W��u!3�CD���f��Sϥ��c⺼Z~�_�wr�D"Md׭:C*�3�\]p�L��
data.tar.gz.sig DELETED
Binary file
data/Guardfile DELETED
@@ -1,8 +0,0 @@
1
- # A sample Guardfile
2
- # More info at https://github.com/guard/guard#readme
3
-
4
- guard 'rspec' do
5
- watch(%r{^spec/.+_spec\.rb$})
6
- watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
- watch('spec/spec_helper.rb') { "spec" }
8
- end
metadata.gz.sig DELETED
Binary file