• Stars
    star
    93
  • Rank 349,416 (Top 8 %)
  • Language
    Ruby
  • Created almost 12 years ago
  • Updated over 10 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Activities recording and retrieving using a simple Pub/Sub-like interface.

Bustle endorse Build Status Dependency Status Code Climate

Activities recording and retrieving using a simple Pub/Sub-like interface.

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 is ORM-agnostic therefore can be extended to use with other databases
  • It has full unit test coverage

Bustle is built for simplicity and extensibility. If you are after high performance pub/sub then this gem is not for you.

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,       :default => ''
      t.text    :data,         :default => ''
      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

# returns a subscriber instance upon duplicated entry
Bustle::Subscribers.add subscriber
# raises error upon duplicated entry
Bustle::Subscribers.add! subscriber

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

Register a Publisher

# returns a publisher instance upon duplicated entry
Bustle::Publishers.add publisher
# raises error upon duplicated entry
Bustle::Publishers.add! publisher

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

Create a Subscription

# returns a subscription instance upon duplicated entry
Bustle::Subscriptions.add bustle_publisher, bustle_subscriber
# raises error upon duplicated entry
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 use `remove!` to raise an exception if the resource cannot be found

Or:

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

Find Referenced Resources

These are helpful for finding referenced resources.

Bustle::Activity#publisher_resource
Bustle::Activity#target_resource
Bustle::Publisher#target_resource
Bustle::Subscriber#target_resource
Bustle::Subscription#publisher_resource
Bustle::Subscription#subscriber_resource

Publish an Activity

Bustle::Activities.add bustle_publisher, {
  :resource => some_resource,
  :action   => some_string,
  :data     => some_text
}
# or
Bustle::Publisher.publish({
  :resource => some_resource,
  :action   => some_string,
  :data     => some_text
})

# 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({
  :resource => comment,
  :action   => 'new',
  :data     => 'useful for putting serialized data or JSON here'
})

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.

Bitdeli Badge

More Repositories

1

crawler

A high performance web crawler / scraper in Elixir.
Elixir
917
star
2

jquery-endless-scroll

Endless/infinite scrolling/pagination.
CoffeeScript
838
star
3

angel_nest

Project code name: Angel Nest. :)
Ruby
775
star
4

api_taster

A quick and easy way to visually test your Rails application's API.
Ruby
728
star
5

simple_bayes

A Naive Bayes machine learning implementation in Elixir.
Elixir
392
star
6

datamappify

Compose, decouple and manage domain logic and data persistence separately. Works particularly great for composing form objects!
Ruby
332
star
7

opq

Elixir queue! A simple, in-memory queue with worker pooling and rate limiting in Elixir.
Elixir
255
star
8

stemmer

An English (Porter2) stemming implementation in Elixir.
Elixir
149
star
9

ruby_decorators

Ruby method decorators inspired by Python.
Ruby
63
star
10

inherited_resources_views

Share and DRY up views between resources. Use with Inherited Resources.
Ruby
60
star
11

jquery-inline-confirmation

Inline Confirmation plugin for jQuery. One of the less obtrusive ways of implementing confirmation dialogues.
JavaScript
53
star
12

toy-robot-elixir

The infamous Toy Robot code test done in Elixir.
Elixir
45
star
13

skinny-coffee-machine

A simple JavaScript state machine with observers, for browsers and Node.js.
JavaScript
42
star
14

kohana-phamlp

This module is a bridge between the Kohana PHP framework (http://kohanaframework.org/) and the PHamlP library (http://code.google.com/p/phamlp/).
PHP
25
star
15

authlite

Authlite, an auth module for Kohana PHP framework, it offers greater flexibility than the official Auth module.
PHP
23
star
16

dotfiles

My dotfiles
Shell
18
star
17

amaze_hands

Amaze Hands is an amazing tool developed for analysing Kanban board cards.
Ruby
15
star
18

kthrottler

A Kohana port of Action Throtller (for Rails): http://github.com/fredwu/action_throttler
PHP
14
star
19

jquery-slideshow-lite

An extremely lightweight slideshow plugin for jQuery.
JavaScript
14
star
20

code-test-2016-cultureamp

Ruby
13
star
21

README-xplor

Fred @ Xplor - how to work with me.
10
star
22

code-test-2016-myob

Ruby
8
star
23

code-test-2016-trunkplatform

Ruby
6
star
24

action_throttler

An easy to use Rails plugin to quickly throttle application actions based on configurable duration and limit.
Ruby
6
star
25

app_reset

Resets (and if available, seeds) your databases.
Ruby
6
star
26

yield.rb

Aggregated token amounts and values. Supports ApeBoard, YieldWatch, Binance, CoinGecko and more.
Ruby
5
star
27

layerful

Layerful PHP framework.
4
star
28

advent_of_code_2018

https://adventofcode.com/2018/about
Elixir
4
star
29

security_guard

A collection of useful tools for auditing data and performing security checks.
Ruby
3
star
30

ruby-slim-tmbundle

https://github.com/slim-template/ruby-slim.tmbundle
3
star
31

fredwu.me-v3

JavaScript
3
star
32

flower

Playground to test out the Lotus framework.
Ruby
2
star
33

kata-poker-hands-elixir

A coding kata for comparing poker hands - Elixir version.
Elixir
2
star
34

jqstub

A simple stub library for jQuery / Zepto objects.
JavaScript
1
star
35

project_retard

One sale a day e-commerce platform built on Ruby on Rails.
JavaScript
1
star
36

toy-robot-lolz

It's art. And it's beautiful.
Ruby
1
star
37

reacraft

Ruby
1
star
38

kata-poker-hands-ruby

A coding kata for comparing poker hands - Ruby version.
Ruby
1
star
39

spiky_xml

Just a spike on XML parsing in different environments.
JavaScript
1
star
40

code-test-2016-adslot

CoffeeScript
1
star