Sorting tables by columns

What I’m trying to do is have clickable column headers that will sort
the table by that column. What I have below works, except there is only
one variable storing the sort direction for all the columns, whereas I
need a separate one for each column name.

list view:

<%= link_to 'Category', :action => 'list', :order => 'categories.category' %> <%= link_to 'Amount', :action => 'list', :order => 'amount' %> <%= link_to 'Date', :action => 'list', :order => 'date' %> <%= link_to 'Location', :action => 'list', :order => 'location' %> <%= link_to 'Note', :action => 'list', :order => 'note' %>


order = @params[:order] ||= ‘date’

unless session[:dir]
session[:dir] = ’ asc’

session[:dir] = (session[:dir] == ’ desc’) ? ’ asc’ : ’ desc’

@all = Activity.find(:all, :order => order + session[:dir], :include =>

I’d like the session hash to be something like:

session = {
:dir => {:date => ’ asc’, :location => ’ desc’, :amount => ’ desc’}

I need to do something like session[:dir][order] but I don’t know the
proper syntax. Ideas?


On 1/8/06, Chris S. [email protected] wrote:

What I’m trying to do is have clickable column headers that will sort
the table by that column.

Do you have an aversion to doing this with Javascript? See for an example.

If you want to do it on the server:

@all = Activity.find(:all, :order => “#{@order}
#{session[:dir][@order.to_sym]}”, :include =>


I’ve been patching something like this together recently for my own app.
I can describe it briefly for you.

== Templates ==

In the templates I put a link much like yours into the table header. In
my case I created a helper function that generates the link based on the
column name. The helper also applies a CSS class of “sorted” to the
link if the sorted column is the current one.

the helper looks something like this

== application_helper file or controller_helper

def sorted_column(name,ukey = nil)
key = ukey || name #allows the passed parameter name to be set
#otherwise it uses the column name
link_to “#{name}”, :sort=>key,
{“class”=>(key == @sort)?“sorted”:“unsorted”}

== Controller ==

def list
@sort = params[:sort] || session[:sort] || “default”
session[:sort] = @sort
@person_pages, @people = paginate :people, :order => sorted_by(@sort)

def sorted_by(key)

This is important because it prevents SQL injection and provides


behavior if naughty users change the URL. It also keeps the URLS

case key
when “lastname” : “lastname, firstname”
else “firstname, lastname”

It isn’t too difficult to set this up in your application controller
with some default settings to give all controllers this action.

** reasons not to use javascript.
If you have a lot of records, you would need to pull them all and send
them to the client to get it to properly sort. Otherwise you would only
be sorting the 10 records it pulled the first time.

I’m typing this from memory, so expect bugs.

This whole thing could be AJAX’d too, but I haven’t gotten to that yet.

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs