# Sorting tables by columns

**URL:** <https://www.ruby-forum.com/t/sorting-tables-by-columns/51895>\
**Category:** Rails\
**Created:** [January 8, 2006, 10:45pm UTC](https://www.ruby-forum.com/t/sorting-tables-by-columns/51895 "2006-01-08T22:45:51Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![yetanothergeek](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/y/8e8cbc/32.png) [@yetanothergeek](https://www.ruby-forum.com/u/yetanothergeek)\
**Post date:** [January 8, 2006, 10:45pm UTC](https://www.ruby-forum.com/t/sorting-tables-by-columns/51895/1 "2006-01-08T22:45:51Z")

</div>

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' %\>

list:

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

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

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

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

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

session = {  
:dir =\> {:date =\> ’ asc’, :location =\> ’ desc’, :amount =\> ’ desc’}  
#etc…  
}

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

Thanks,  
Chris

---

<div class="post-metadata">

**Author:** ![yetanothergeek](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/y/8e8cbc/32.png) [@yetanothergeek](https://www.ruby-forum.com/u/yetanothergeek)\
**Post date:** [January 8, 2006, 11:30pm UTC](https://www.ruby-forum.com/t/sorting-tables-by-columns/51895/2 "2006-01-08T23:30:22Z")

</div>

On 1/8/06, Chris S. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) 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  
[sorttable: Make all your tables sortable](http://www.kryogenix.org/code/browser/sorttable/) for an example.

If you want to do it on the server:

@all = Activity.find(:all, :order =\> “#{@order}  
#{session[:dir][@order.to\_sym]}”, :include =\>  
:category)

---

<div class="post-metadata">

**Author:** ![yetanothergeek](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/y/8e8cbc/32.png) [@yetanothergeek](https://www.ruby-forum.com/u/yetanothergeek)\
**Post date:** [January 9, 2006, 6:18am UTC](https://www.ruby-forum.com/t/sorting-tables-by-columns/51895/3 "2006-01-09T06:18:08Z")

</div>

Chris,

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”}  
end

== Controller ==

def list  
@sort = params[:sort] || session[:sort] || “default”  
session[:sort] = @sort  
@person\_pages, @people = paginate :people, :order =\> sorted\_by(@sort)  
end

def sorted\_by(key)

# This is important because it prevents SQL injection and provides

default

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

clean.  
case key  
when “lastname” : “lastname, firstname”  
else “firstname, lastname”  
end  
end

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.
