Module: SortHelper

Overview

Helpers to sort tables using clickable column headers.

Author: Stuart Rackham <srackham@methods.co.nz>, March 2005.

Jean-Philippe Lang, 2009

License: This source code is released under the MIT license.

  • Consecutive clicks toggle the column's sort order.

  • Sort state is maintained by a session hash entry.

  • CSS classes identify sort column and state.

  • Typically used in conjunction with the Pagination module.

Example code snippets:

Controller:

helper :sort
include SortHelper

def list
  sort_init 'last_name'
  sort_update %w(first_name last_name)
  @items = Contact.find_all nil, sort_clause
end

Controller (using Pagination module):

helper :sort
include SortHelper

def list
  sort_init 'last_name'
  sort_update %w(first_name last_name)
  @contact_pages, @items = paginate :contacts,
    :order_by => sort_clause,
    :per_page => 10
end

View (table header in list.rhtml):

<thead>
  <tr>
    <%= sort_header_tag('id', :title => 'Sort by contact ID') %>
    <%= sort_header_tag('last_name', :caption => 'Name') %>
    <%= sort_header_tag('phone') %>
    <%= sort_header_tag('address', :width => 200) %>
  </tr>
</thead>
  • Introduces instance variables: @sort_default, @sort_criteria

  • Introduces param :sort

Defined Under Namespace

Classes: SortCriteria

Instance Method Summary collapse

Instance Method Details

#sort_clauseObject

Returns an SQL sort clause corresponding to the current sort state. Use this to sort the controller's table items collection.



169
170
171
# File 'app/helpers/sort_helper.rb', line 169

def sort_clause()
  @sort_criteria.to_sql
end

#sort_clearObject

Clears the sort criteria session data



162
163
164
# File 'app/helpers/sort_helper.rb', line 162

def sort_clear
  session[sort_name] = nil
end

#sort_header_tag(column, options = {}) ⇒ Object

Returns a table header <th> tag with a sort link for the named column attribute.

Options:

:caption     The displayed link name (defaults to titleized column name).
:title       The tag's 'title' attribute (defaults to 'Sort by :caption').

Other options hash entries generate additional table header tag attributes.

Example:

<%= sort_header_tag('id', :title => 'Sort by contact ID', :width => 40) %>


219
220
221
222
223
224
# File 'app/helpers/sort_helper.rb', line 219

def sort_header_tag(column, options = {})
  caption = options.delete(:caption) || column.to_s.humanize
  default_order = options.delete(:default_order) || 'asc'
  options[:title] = l(:label_sort_by, "\"#{caption}\"") unless options[:title]
  ('th', sort_link(column, caption, default_order), options)
end

#sort_init(*args) ⇒ Object

Initializes the default sort. Examples:

sort_init 'name'
sort_init 'id', 'desc'
sort_init ['name', ['id', 'desc']]
sort_init [['name', 'desc'], ['id', 'desc']]


137
138
139
140
141
142
143
144
145
146
# File 'app/helpers/sort_helper.rb', line 137

def sort_init(*args)
  case args.size
  when 1
    @sort_default = args.first.is_a?(Array) ? args.first : [[args.first]]
  when 2
    @sort_default = [[args.first, args.last]]
  else
    raise ArgumentError
  end
end

Returns a link which sorts by the named column.

  • column is the name of an attribute in the sorted record collection.

  • the optional caption explicitly specifies the displayed link text.

  • 2 CSS classes reflect the state of the link: sort and asc or desc



179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'app/helpers/sort_helper.rb', line 179

def sort_link(column, caption, default_order)
  css, order = nil, default_order
  
  if column.to_s == @sort_criteria.first_key
    if @sort_criteria.first_asc?
      css = 'sort asc'
      order = 'desc'
    else
      css = 'sort desc'
      order = 'asc'
    end
  end
  caption = column.to_s.humanize unless caption
  
  sort_options = { :sort => @sort_criteria.add(column.to_s, order).to_param }
  # don't reuse params if filters are present
  url_options = params.has_key?(:set_filter) ? sort_options : params.merge(sort_options)
  
   # Add project_id to url_options
  url_options = url_options.merge(:project_id => params[:project_id]) if params.has_key?(:project_id)

  link_to_remote(caption,
                {:update => "content", :url => url_options, :method => :get},
                {:href => url_for(url_options),
                 :class => css})
end

#sort_nameObject



125
126
127
# File 'app/helpers/sort_helper.rb', line 125

def sort_name
  controller_name + '_' + action_name + '_sort'
end

#sort_update(criteria) ⇒ Object

Updates the sort state. Call this in the controller prior to calling sort_clause.

  • criteria can be either an array or a hash of allowed keys



152
153
154
155
156
157
158
# File 'app/helpers/sort_helper.rb', line 152

def sort_update(criteria)
  @sort_criteria = SortCriteria.new
  @sort_criteria.available_criteria = criteria
  @sort_criteria.from_param(params[:sort] || session[sort_name])
  @sort_criteria.criteria = @sort_default if @sort_criteria.empty?
  session[sort_name] = @sort_criteria.to_param
end