README.md in wisper-1.0.1 vs README.md in wisper-1.1.0

- old
+ new

@@ -30,11 +30,11 @@ ### Publishing ```ruby class MyPublisher - include Wisper + include Wisper::Publisher def do_something # ... publish(:done_something, self) end @@ -69,71 +69,68 @@ my_publisher.on(:done_something) do |publisher| # ... end ``` -### Asynchronous Publishing (Experimental) +### Asynchronous Publishing -There is support for publishing events asynchronously by passing the `async` -option. +Please refer to the [wisper-async](https://github.com/krisleech/wisper-async) gem. -```ruby -my_publisher.add_subscriber(MySubscriber.new, :async => true) -``` - -This leans on Celluloid, which must be included in your Gemfile. - -The listener is transparently turned in to a Celluloid Actor. - -Please refer to [Celluloid](https://github.com/celluloid/celluloid/wiki) -for more information, particually the -[Gotchas](https://github.com/celluloid/celluloid/wiki/Gotchas). - ### ActiveRecord ```ruby -class Post < ActiveRecord::Base - include Wisper +class Bid < ActiveRecord::Base + include Wisper::Publisher - def create - if save - publish(:create_post_successful, self) + validates :amount, :presence => true + + def commit(_attrs = nil) + assign_attributes(_attrs) if _attrs.present? + if valid? + save! + publish(:create_bid_successful, self) else - publish(:create_post_failed, self) + publish(:create_bid_failed, self) end end end ``` ### ActionController ```ruby -class PostsController < ApplicationController +class BidsController < ApplicationController + def new + @bid = Bid.new + end + def create - @post = Post.new(params[:post]) + @bid = Bid.new(params[:bid]) - @post.subscribe(PusherListener.new) - @post.subscribe(ActivityListener.new) - @post.subscribe(StatisticsListener.new) + @bid.subscribe(PusherListener.new) + @bid.subscribe(ActivityListener.new) + @bid.subscribe(StatisticsListener.new) - @post.on(:create_post_successful) { |post| redirect_to post } - @post.on(:create_post_failed) { |post| render :action => :new } + @bid.on(:create_bid_successful) { |bid| redirect_to bid } + @bid.on(:create_bid_failed) { |bid| render :action => :new } - @post.create + @bid.commit end end ``` +A full CRUD example is shown in the [Wiki](https://github.com/krisleech/wisper/wiki). + ### Service/Use Case/Command objects A Service object is useful when an operation is complex, interacts with more than one model, accesses an external API or would burden a model with too much responsibility. ```ruby class PlayerJoiningTeam - include Wisper + include Wisper::Publisher def execute(player, team) membership = Membership.new(player, team) if membership.valid? @@ -208,10 +205,28 @@ Wisper::GlobalListeners.add_listener(MyListener.new) ``` In a Rails app you might want to add your global listeners in an initalizer. +Global listeners are threadsafe. + +## Temporary Global Listeners + +You can also globally subscribe listeners for the duration of a block. + +```ruby +Wisper.with_listeners(MyListener.new, OtherListener.new) do + # do stuff +end +``` + +Any events broadcast within the block by any publisher will be sent to the +listeners. This is useful if you have a child object which publishes an event +which is not bubbled down to a parent publisher. + +Temporary Global Listeners are threadsafe. + ## Subscribing to selected events By default a listener will get notified of all events it can respond to. You can limit which events a listener is notified of by passing an event or array of events to `:on`. @@ -309,10 +324,11 @@ See `spec/lib/rspec_extensions_spec.rb` for a runnable example. ## Compatibility -Tested with 1.9.x on MRI, JRuby and Rubinius. +Tested with MRI 1.9.x, MRI 2.0.0, JRuby (1.9 and 2.0 mode) and Rubinius (1.9 +mode). See the [build status](https://travis-ci.org/krisleech/wisper) for details. ## License (The MIT License)