module WillPaginate::Finders::ActiveRecord

Paginating finders for ActiveRecord models

WillPaginate adds paginate, per_page and other methods to ActiveRecord::Base class methods and associations. It also hooks into method_missing to intercept pagination calls to dynamic finders such as paginate_by_user_id and translate them to ordinary finders (find_all_by_user_id in this case).

In short, paginating finders are equivalent to ActiveRecord finders; the only difference is that we start with “paginate” instead of “find” and that :page is required parameter:

@posts = Post.paginate :all, :page => params[:page], :order => 'created_at DESC'

In paginating finders, “all” is implicit. There is no sense in paginating a single record, right? So, you can drop the :all argument:

Post.paginate(...)              =>  Post.find :all
Post.paginate_all_by_something  =>  Post.find_all_by_something
Post.paginate_by_something      =>  Post.find_all_by_something

Public Instance Methods

paginate_by_sql(sql, options) click to toggle source

Wraps find_by_sql by simply adding LIMIT and OFFSET to your SQL string based on the params otherwise used by paginating finds: page and per_page.

Example:

@developers = Developer.paginate_by_sql ['select * from developers where salary > ?', 80000],
                       :page => params[:page], :per_page => 3

A query for counting rows will automatically be generated if you don’t supply :total_entries. If you experience problems with this generated SQL, you might want to perform the count manually in your application.

# File lib/will_paginate/finders/active_record.rb, line 43
def paginate_by_sql(sql, options)
  WillPaginate::Collection.create(*wp_parse_options(options)) do |pager|
    query = sanitize_sql(sql.dup)
    original_query = query.dup
    # add limit, offset
    add_limit! query, :offset => pager.offset, :limit => pager.per_page
    # perfom the find
    pager.replace find_by_sql(query)
    
    unless pager.total_entries
      count_query = original_query.sub /\bORDER\s+BY\s+[\w`,\s]+$/i, ''
      count_query = "SELECT COUNT(*) FROM (#{count_query})"
      
      unless ['oracle', 'oci'].include?(self.connection.adapter_name.downcase)
        count_query << ' AS count_table'
      end
      # perform the count query
      pager.total_entries = count_by_sql(count_query)
    end
  end
end