Simple event-based publish-subscribe library
Switch branches/tags
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.


Build Status Code Climate Coverage Status

PubSubHub allows you to loosen the coupling between components in a system by providing a centralized registry of events and listeners that subscribe to those events.

For example, given a method #foo, on class Bar, with a slew of side-effects (communication with multiple classes outside of Bar), you effectively have tightly coupled Bar to a number of different classes in the system. Any change to those other classes on which Bar depends may break it. PubSubHub provides a pattern in which Bar can be freed of its dependencies: the parts of the system that care when #foo happens can subscribe to an event, and Bar need not even know that those other parts exist.

You can learn more about the motivation behind PubSubHub in our blog post, "Managing side-effects with the Pub-Sub model".


Add this line to your application's Gemfile:

gem 'pubsubhub'

And then execute:

$ bundle

Or install it yourself as:

$ gem install pubsubhub


PubSubHub provides a mechanism to subscribe to events and notify objects of events.

To set up event listeners, pass a hash of events and listeners as follows:

  took_action: [
    { listener: 'Mailer', async: true },

To trigger an event, call PubSubHub.trigger. All the arguments are forwarded to the listener.

class Action
  def take_action(person)
    # ...
    PubSubHub.trigger :took_action, self, person

class Mailer
  def self.handle_took_action(action, person)
    # send `action.creator` an email

By default, exceptions raised during event propagation are handled by printing them to standard error. You can set a custom handler by passing in a callable object to PubSubHub.error_handler=. We use this at Causes to integrate with our Oops plug-in, without creating a hard dependency on it:

PubSubHub.error_handler = ->(exception) { Oops.log(exception) }

Likewise, dispatch of async: true events is handled by a callable passed in to PubSubHub.async_dispatcher=. The default implementation just calls Object#send (ie. it is not actually asynchronous). At Causes, we've supplied a custom dispatcher that relies on the async_observer plug-in:

PubSubHub.async_dispatcher = ->(listener, handler, args) do
  listener.async_send(handler, *args)

Note that PubSubHub is usable in any Ruby application; we happen to use it in a Rails application, and make the call to PubSubHub.register in a file in the config/initializers/ directory.


PubSubHub requires Ruby 2.0 or above.


PubSubHub is built by Causes.