module PageAndSortHelper::Controller

Public Instance Methods

page_and_sort(scope, options={}) click to toggle source

return the given scope paged and sorted according to the query modifiers present in params. This includes:

  1. Using kaminari for paging long lists.

  2. Sorting the results by params in the params direction (default to ASC)

Note, complex order bys can be delegated to a class method (or scope) which will be passed the direction (“asc” or “desc”). The class method / scope should be named “order_by_” followed by the name of the sort.

For example: class Model < ActiveRecord::Base

scope :order_by_complex_thing, lamda { |direction| order("complex order clause here") }

end

And use this by params = “complex_thing”

# File lib/page_and_sort_helper.rb, line 54
def page_and_sort(scope, options={})

  # get the ActiveRecord class for the scope.
  klass =
      case
        when Array
          scope
        when scope.respond_to?(:scoped)
          scope.scoped.klass
        when ActiveRecord::Base
          scope.all
        else
          scope
      end

  # save the sorting object class, so that it can be used as the localisation scope to look up the attribute
  # name for the link
  @_sort_klass = klass

  # apply the order scope if present, prefering a class method / scope if defined, otherwise composing the clause
  # using arel attributes so the sort order is safe to use with queries with joins, etc.
  field = sort_column || options[:default_sort]
  if field
    # save the sort order in the controller's instance variables where it can be accessed by the view helper
    # above to show the current sort order even if it is not specified by params[:sort]
    @_sort_order = field
    @_sort_direction = sort_direction(options[:default_direction])

    scope =
        if klass.respond_to? "order_by_#{field}"
          scope.__send__ "order_by_#{field}", @_sort_direction
        else
          attribute = klass.arel_table[field]
          scope.order(@_sort_direction == :asc ? attribute.asc : attribute.desc)
        end
  end

  # apply kaminari pagination
  if scope.respond_to?(:page) && !options[:skip_pagination]
    scope.page(params[:page])
  else
    scope
  end
end