December 11, 2006
Older: BDD and Setting Up Controllers
Newer: Speeding Up Prototype's $ Function
Pimping Find
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 Comments
Dec 11, 2006
I’d go with “@things = current_user.things” and extend the User model instead.
Dec 11, 2006
I think I like that better. I’m not sure, I’ll have to try it out.
Dec 12, 2006
Yep, the definition of “all” is user specific so it makes logical sense for the rules to be defined within the User model.
Dec 14, 2006
Another vote for moving this kind of thing to the User model, less brain twisty. (interesting blog btw!)
Sorry, comments are closed for this article to ease the burden of pruning spam.