Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Activities recording and retrieving using a simple Pub/Sub-like interface.
tag: v0.1.0

Fetching latest commit…

Cannot retrieve the latest commit at this time

Failed to load latest commit information.
lib
specs
.gitignore
.rspec
.travis.yml
Gemfile
README.md
Rakefile
bustle.gemspec

README.md

Bustle Build Status Dependency Status Code Climate

Activities recording and retrieving using a simple Pub/Sub architecture.

The typical use cases are:

  • Timeline (e.g. tracking activities such as posting and commenting for users)
  • Logging

The advantages of Bustle are:

  • It is lightweight and simple to use
  • It is largely self-contained and separated from you core app logic
  • It works nicely with ActiveRecord out of box
  • It can be extended to use with other databases
  • It has full unit test coverage

Installation

Add this line to your application's Gemfile:

gem 'bustle'

Usage

Configuration

First of all, you will need to configure Bustle. If you are using Rails, you can put the following code in an initializer (e.g. config/initializers/bustle.rb).

Bustle.config do |c|
  # Specify a storage strategy for storing activities
  # Bustle ships with an ActiveRecord storage strategy
  c.storage = Bustle::Storage::ActiveRecord
end

For ActiveRecord, you will need the following migration file:

class CreateBustleTables < ActiveRecord::Migration
  def change
    create_table :bustle_activities do |t|
      t.string  :resource_class
      t.integer :resource_id
      t.string  :action
      t.integer :publisher_id, :null => false
      t.timestamps
    end

    create_table :bustle_publishers do |t|
      t.string  :resource_class, :null => false
      t.integer :resource_id,    :null => false
      t.timestamps
    end

    create_table :bustle_subscribers do |t|
      t.string  :resource_class, :null => false
      t.integer :resource_id,    :null => false
      t.timestamps
    end

    create_table :bustle_subscriptions do |t|
      t.integer :publisher_id,  :null => false
      t.integer :subscriber_id, :null => false
      t.timestamps
    end

    add_index :bustle_activities, :publisher_id
    add_index :bustle_publishers, [:resource_class, :resource_id], :unique => true
    add_index :bustle_subscribers, [:resource_class, :resource_id], :unique => true
    add_index :bustle_subscriptions, :publisher_id
    add_index :bustle_subscriptions, :subscriber_id
    add_index :bustle_subscriptions, [:publisher_id, :subscriber_id], :unique => true
  end
end

Flow

Upon subscribing:

  1. Subscriber registers itself if not already registered
  2. Publisher registers itself if not already registered
  3. A Subscription is created for Subscriber and Publisher

When activities occur:

  1. Publisher registers itself if not already registered
  2. Publisher publishes activity

API

Register a Subscriber

Bustle::Subscribers.add subscriber

# example
user = User.find(1)
Bustle::Subscribers.add user

Register a Publisher

Bustle::Publishers.add publisher

# example
post = Post.find(1)
Bustle::Publishers.add post

Create a Subscription

Bustle::Subscriptions.add bustle_publisher, bustle_subscriber

# example
publisher  = Bustle::Publishers.get(Post.first)
subscriber = Bustle::Subscribers.get(User.first)
Bustle::Subscriptions.add publisher, subscriber

Find a Subscriber/Publisher/Subscription

Bustle::Subscribers.get subscriber
Bustle::Publishers.get publisher
Bustle::Subscriptions.get bustle_publisher, bustle_subscriber # => Bustle::Subscription
Bustle::Subscriptions.by bustle_publisher # => an array of Bustle::Subscription by the publisher
Bustle::Subscriptions.for bustle_subscriber # => an array of Bustle::Subscription for the subscriber

Remove a Subscriber/Publisher/Subscription

Bustle::Subscribers.remove subscriber
Bustle::Publishers.remove publisher
Bustle::Subscriptions.remove bustle_publisher, bustle_subscriber

Or:

Bustle::Subscribers.get(subscriber).destroy
Bustle::Publishers.get(publisher).destroy
Bustle::Subscriptions.get(bustle_publisher, bustle_subscriber).destroy

Publish an Activity

Bustle::Activities.add bustle_publisher, action, activity
# or
Bustle::Publisher.publish action, activity

# example
post    = Post.find(1)
comment = post.comments.add(:content => "I'm a comment")
Bustle::Publishers.add post
publisher = Bustle::Publishers.get post
publisher.publish 'new', comment

Activities

Retrieve Activities for a Subscriber
Bustle::Activities.for bustle_subscriber
# or
Bustle::Subscriber.activities

# example
subscriber = Bustle::Subscribers.get(User.first)
subscriber.activities
Retrieve Activities by a Publisher
Bustle::Activities.by bustle_publisher
# or
Bustle::Publisher.activities

# example
publisher = Bustle::Publishers.get(Post.first)
publisher.activities

Filtering (for Activities and Subscriptions)

Bustle::Activities.filter :key => :value
Bustle::Subscriptions.filter :key => :value
# or
Bustle::Subscriber.activities :key => :value

# example
subscriber = Bustle::Subscribers.get(User.first)
subscriber.activities :action => 'new'

License

This gem is released under the MIT License.

Author

Fred Wu, originally built for 500 Startups.

Something went wrong with that request. Please try again.