Active Resource Callbacks

Posted by paul
on 27 August 2008

It looks like work is still on-going to extract functionality common to Active Record and Active Resource into a new Active Model library. Excellent. But I wanted to add a couple of callbacks to Active Resource and I wanted to do it quickly. Thankfully, someone much smarter than me has already extracted callbacks from Active Record, so getting something working was pretty straight forward.

module ActiveResource
  module Callbacks
    CALLBACKS = %w( after_save after_destroy )
    
    def self.included(base)
      [:save, :destroy].each do |method|
        base.send :alias_method_chain, method, :callbacks
      end
      
      base.send :include, ActiveSupport::Callbacks
      base.define_callbacks *CALLBACKS
    end
    
    def save_with_callbacks
      returning save_without_callbacks do
        run_callbacks(:after_save) unless new?
      end
    end
    
    def destroy_with_callbacks
      returning destroy_without_callbacks do
        run_callbacks(:after_destroy)
      end
    end
  end
end

ActiveResource::Base.send :include, ActiveResource::Callbacks

resourceful_pagination

Posted by paul
on 03 August 2008

I've been doing quite a bit of work recently on an Active Resource project and needed to add pagination to one of our resources. I had a quick look around to see what other people were doing, and while it looks like work is underway to add support for Active Resource (and ORMs other than Active Record) to will_paginate I don't think it's quite ready just yet. So while we wait, may I present resourceful_pagination.

If you want to dive straight in, take a look at the readme then install the gem with:

sudo gem install phorsfall-resourceful_pagination --source http://gems.github.com

With the gem installed you get a shiny new ActiveResource::Base#paginate method. Use it like this:

MyResource.paginate(:page => params[:page])

This returns a WillPaginate::Collection which you can use with will_paginate's view helpers as usual.

Easy, right?, Well, sort of. The gem makes a few assumptions about your Active Resource class and your RESTful resource. If you want to use this you'll probably need to make a few changes. First you need to add two class methods to your Active Resources.

  1. A count method which returns the total number of items. This could call a custom count action on the app server.
  2. A per_page method indicating how many records you require per page.

Something like this would do the trick:

class MyResource < ActiveResource::Base
  @@per_page = 10
  cattr_reader :per_page

  def self.count
    get(:count)['count']
  end
end

You also need the index action of the controller on the app server to handle the :starting_at and :per_page parameters. These map to :offset and :limit in SQL and can be passed straight through to Active Record.

MyResourcesController < ApplicationController
  def index
    MyResource.find :all, :limit => params[:per_page], :offset => params[:starting_at]
    # Render XML etc.
  end

  def count
    count = MyResource.count
    render :xml => { :count => count }
  end
end

And that's about it. There's a little bit more to do if you have a nested resource, but there's a bit more on that in the readme.

Enjoy.