Module: SortHelper

Overview

Helpers to sort tables using clickable column headers.

Author: Stuart Rackham <[email protected]>, 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.



178
179
180
# File 'app/helpers/sort_helper.rb', line 178

def sort_clause()
  @sort_criteria.to_sql
end

#sort_clearObject

Clears the sort criteria session data



171
172
173
# File 'app/helpers/sort_helper.rb', line 171

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) %>


228
229
230
231
232
233
# File 'app/helpers/sort_helper.rb', line 228

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']]


146
147
148
149
150
151
152
153
154
155
# File 'app/helpers/sort_helper.rb', line 146

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



188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
# File 'app/helpers/sort_helper.rb', line 188

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



134
135
136
# File 'app/helpers/sort_helper.rb', line 134

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



161
162
163
164
165
166
167
# File 'app/helpers/sort_helper.rb', line 161

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