MakesEvents

Overview

MakesEvents makes it easy to create running logs of user activity. Why would you want to do that? Well, the reason I made it is because I wanted a Facebook-like feed of recent user activity on a particular site (heavyink.com). The naive first-pass implementation involved grabbing the records from the last x days for a particular user from a variety of tables. (Something like 20.) This obviously would not scale. What you’d actually want to do is just note particular user activity in a single table so you can just select from there and be done with it.

Example


    class User < ActiveRecord::Base
      owns_events
    end

    class Pet < ActiveRecord::Base
      belongs_to :user

      makes_events :owner => :user do
        event :new_pet, :after_create
        event :pet_died, :after_destroy
        event :pet_changed_names, :after_update, :changed => :name
        event :got_a_monkey, :after_save do |pet|
          pet.type_changed? && pet.type == 'monkey'
        end
      end
    end
  

Here we have a trivial example where we have Users who have Pets. We want to log every time a user saves a new pet, deletes a pet, changes a pet’s name, or when the pet is a monkey.

First we say that Pets make events using the makes_events method. We can pass a hash of options to that method which propagate down to the individual event methods within the block.

The individual event calls are fairly straightforward. The first creates the :new_pet event type, which gets triggered on the after_create callback. Likewise, we make a :pet_died event type which gets triggered on the after_destroy callback.

The third event is slightly more complicated in that it relies on the :changed option. In this case, we want the event to be triggered on the after_update callback, but only if the name field has changed. (This relies on Rails 2.1’s Dirty fields functionality.)

The last event call is more complicated yet. Passing a block to event allows you to control whether or not the event is triggered based on the return value of that block. In this case, the event will only be triggered if the pet’s type has been set to “monkey”. One important note is that the block you pass to it will actually be run in a before_save callback. This allows you to check whether a field has been changed and trigger the event based on that.