ActiveEvent: My latest plugin

For one of my current applications I had a need for an event handling system.

I needed to able to dispatch events during the application’s lifecycle, and have observers respond to them appropriately. I also needed to keep an audit trail of the user’s interaction with the application.

Rails has the basis of an event handling system for ActiveRecord models in the form of it’s callbacks that ActiveRecord::Observer’s can react upon. However, this is limited to a set amount of callbacks and doesn’t support a wide variety of events.

So I wrote ActiveEvent to do this.

I actually wrote this code about a year ago for Rails 1.0 when I was developing ocium.com but I’ve since needed this for one of our current internal applications and I’ve refactored and packaged into a plugin that others can use.

“What do I use this for and how do I use it?” – A very good question.

Use it for:

  1. Creating an synchronous order event handling system with events like OrderPlacedEvent, OrderShippedEvent, OrderRefusedEvent. Have observers that react to each event in a distinct and customised way. Perhaps, you want to send an email informing the client of the fact that their order has been shipped (very simple use case). Your imagination is the limit.

(NOTE: ActiveEvent in combination with the ActsAsStatemachine plugin makes for a very powerful way of controlling your application’s lifecycle.)

  1. Want to be able to easily track a users actions within your application? This plugin makes this a piece of cake.

Let’s see it in action

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

class Order < ActiveRecord::Base

  has_active_events    #Assumes an existing User model class but is customizable

  def place_order(msg)
    send_event(ActiveEvent::OrderPlacedEvent.new(self, nil, msg)
  end
end

class OrderObserver < ActiveRecord::Observer

  def after_save
    #do something here
  end

  def on_event(order, event)
    #react to the event
    #e.g.
    case Event
      when OrderShippedEvent
        OrderNotifier.deliver_order_shipped(order, event)
      when OrderCancelledEvent
        order.cancel! #Change model state via ActsAsStatemachine plugin
    end

    #Add the event to the audit system
    ActiveEvent::AuditTrail.add_event(event) 
  end
end

Get it installed:

1
2
3
4

script/plugin install svn://rubyforge.org/var/svn/sidirodromos/plugins/active_event/trunk

script/generate active_event migrations

Change coming soon:

  • Add an option to has_active_events method to allow transparent event tracking. i.e. In above example, you’d no longer need to add the ActiveEvent::AuditTrail.add_event(event) call.

e.g.

1
2
3
4

class Order < ActiveRecord::Base
  has_active_events :audit => true
end
  • Make the auditing system completely optional (No need to create its tables unless you want it)
  • Add asynchronous notifications support via the backgroundrb plugin

Actually I thought these todo’s were so important I added them in already :)

Have a look at the plugins README for details and examples. Then have a look at it’s tests.

P.S. I’m thinking about adding support for the Memento pattern to provide granularized undo possibilities…


Back to articles