Sorted is a simple object that will take an sql order string and a url sort string to let you sort large datasets over many pages (using will_paginate) without loosing state.
Using Rails master it will create a sorted scope and a two view helpers
gem sorted
link_to_sorted "Email", :email
This will make a url like this:
http://myapp/users?sort=email_asc
or on the next page load when you then sort by something else.…
http://myapp/users?sort=name_asc!email_asc
This will initially sort by email ascending:
@users = User.sorted(:order => "email ASC", :sort => params[:sort]).paginate(:page => params[:page])
Or you can just clone the example app github.com/mynameisrufus/sorted_app.
If you want to sort by a belongs_to relationship, just provide sort order as “RELATIONS.COLUMN ASC|DESC” where RELATIONS is the name of the relationship table and COLUMN is an attribute in that table. For example, assuming the User model belongs_to a :company.
@users = User.sorted(:order => "companies.name asc", :sort => params[:sort]).paginate(:page => params[:page])
You might want to roll your own link_to_sorted method to use jQuery ui css classes for example, all you need is the sorted object.
def link_to_sorted(name, order) sorter = sorted(order) css_class = case sorter.to_css when "sorted asc" "ui-icon ui-icon-triangle-1-n" when "sorted desc" "ui-icon ui-icon-triangle-1-s" when "sorted" "ui-icon ui-icon-carat-2-n-s" end link_to(content_tag(:span, nil, {:class => css_class}) + name.to_s, sorter.params) end
Tables are best displayed with alternating shades for each row, so put this in your helper:
def odd_even @odd_even ||= 0 @odd_even += 1 (@odd_even % 2) == 1 ? 'odd' : 'even' end
Then in your table do something like this:
<tr class="<%= odd_even %>">
This gem works with rails 2.3.x but you will have to roll your own scope and view helper.
Here is the named scope for your model(s):
named_scope :sorted, lambda { |params| { :order => Sorted::Sorter.new(params[:order], {:sort => params[:sort]}).to_sql } }
and the the application helper methods:
def sorted(order) Sorted::Sorter.new(order, (request.get? && !params.nil?) ? params.dup : nil).toggle end def link_to_sorted(name, order) sorter = sorted(order) link_to(name, sorter.params, {:class => sorter.to_css}) end