Scoping finds in your controllers
7 Feb 2007Here’s a fun one that’s been discussed a little bit here and there. One scenario I encounter pretty regularly is needing to have two different ways to load data from a controller action:
- Load all data (a list of orders, let’s say) when the user loading the action is an admin
- Load a subset of data (a list of just one user’s orders) when the user loading the action is not an admin
There are a few ways you can handle this scenario, but here’s my favorite way (for the time being, at least):
class OrdersController < ApplicationController
def index
@orders = order_finder.find(:all, :order => 'name')
end
protected
def order_finder
current_user.admin? ? Order : current_user.orders
end
end
This is a simplified snippet, but it demonstrates an easy way to change the data being pulled out based on who is using the application. And for no extra charge you can still keep your controller code lean and mean. :)







Doesn’t this cause 2 queries for the non-admin case?
That’s very cool. It never occurred to me to extract out authentication/access in that way. Taa.
s/authentication/authorisation
@Tom – no, in recent Rails versions current_user.orders creates a placeholder association pending a method called upon it.
So for current_user.orders.to_a or current_user.orders.find(:all) it is only then that the SQL is run.
For current_user.orders.find(:all, :conditons=>…, :order=>’created_at’) it is only at the find that an SQL is created and run. Very nifty.
I like it.
I thought this post was going to show a trick using ActiveRecord::Base#with_scope
http://api.rubyonrails.org/classes/ActiveRecord/Base.html#M001024