Pimping Find

December 11th, 2006

Jamis Buck posted not too long ago about making active record finders work for you. In really simple applications, often times I have an admin and some general users. Annoyingly, I often do something like:

class ThingsController < ApplicationController
  before_filter :login_required

  def index
    @things = if current_user.admin?
      Things.find(:all)
    else
      current_user.things
    end

    # respond to the action here
  end
end

The approach I took on my last application, inspired by Jamis’ mods to #find looks like this:

class ThingsController < ApplicationController
  before_filter :login_required

  def index
    @things = Thing.find(current_user, :all)

    # respond to the action here
  end
end

Makes my controller a bit smaller and moves the logic to the model. It’s all possible by the following addition to my Thing model:

class Thing < ActiveRecord::Base
  class << self
    def find(*args)
      user = args.shift if args.first.is_a?(User)
      if user
        # go on like normal if user is admin otherwise scope things to the user passed in
        user.admin? ? super : user.things.find(*args) 
      else
        # go on like normal if no user passed in
        super
      end
    end
  end
end
Thing.find still works just like the original find method unless a user object is the first parameter. If so, it determines exactly which things the user passed in has access to and returns those. Anyone else have a better idea? This is working for me but I’d be open to any better solutions.

4 Responses to “Pimping Find”

  1. Josh Peek Says:

    I’d go with ”@things = current_user.things” and extend the User model instead.

  2. John Nunemaker Says:

    I think I like that better. I’m not sure, I’ll have to try it out.

  3. Nathan de Vries Says:

    Yep, the definition of “all” is user specific so it makes logical sense for the rules to be defined within the User model.

  4. bitbutter Says:

    Another vote for moving this kind of thing to the User model, less brain twisty. (interesting blog btw!)

Leave a Reply


(textile enabled)