Skip to content
Mislav Marohnić edited this page Oct 22, 2019 · 8 revisions

will_paginate documentation

This is the official home for will_paginate library; a collection of extensions for the database layer that enable paginated queries, and view helpers for popular frameworks that render pagination links. With proper combination of view helpers and CSS styling, the final result can look like this:

will_paginate sample rendering

To get started, see Installation instructions.

Should you use this library in your application? See Limitations.

Usage examples

## perform a paginated query:
@posts = Post.paginate(:page => params[:page])

# or, use an explicit "per page" limit:
Post.paginate(:page => params[:page], :per_page => 30)

## render page links in the view:
<%= will_paginate @posts %>

And that's it! You're done. You just need to add some CSS styles to make those pagination links prettier.

You can customize the default "per_page" value:

# for the Post model
class Post
  self.per_page = 10
end

# set per_page globally
WillPaginate.per_page = 10

New in Active Record 3

# paginate in Active Record now returns a Relation
Post.where(:published => true).paginate(:page => params[:page]).order('id DESC')

# the new, shorter page() method
Post.order('created_at DESC').page(params[:page])

Usage in Sinatra

# classic sinatra app style
require "sinatra"
require "will_paginate"

# you can now use `will_paginate` helper in your views

Or:

require "sinatra/base"
require "will_paginate/view_helpers/sinatra"

class MyApp < Sinatra::Base
  register WillPaginate::Sinatra
end

Limitations

This library was designed around the concepts of SQL LIMIT + OFFSET (to fetch a single page's worth of results), SQL COUNT (to calculate the total number of pages), and an opinionated way of rendering pagination links in HTML (links for first and last page are always visible). This approach is outdated and has known limitations:

  • Depending on the database engine and table size, queries may get more expensive as the OFFSET value gets larger. This results in the query for page 20, for example, executing considerably slower than querying page 2.

    To get around these performance concerns, some database engines offer cursor-based pagination, or encourage pagination based on min/max values, e.g. WHERE id > :max_id in which the :max_id value is based on the previous page of results. This approach is usually superior for speed and memory concerns, but comes with some tradeoffs; the most notable being that it's only ever possible to go to the next page of results and not immediately jump to page 20, for example. The will_paginate library does not handle cursor-based pagination.

  • By default, will_paginate will generate an SQL COUNT query to get the total number of results, and thus total number of available pages. Depending on the complexity of the original query and the underlying database engine, the COUNT query may be slow, its results may be inaccurate, or the query might fail.

    To find out whether there is a next page of results, some pagination implementations fetch LIMIT + 1 number of entries for each page, and then generate the next page link if the number of results was greater than LIMIT. They avoid ever fetching the total number of entries. The will_paginate library does not implement this pagination style, primarily because it wants to be able to generate the link to the last page of results.

  • If the database query to be paginated involves SQL JOIN or GROUP BY, applying LIMIT + OFFSET on such queries or trying to generate a COUNT query might fail based on the specific database adapter used. The will_paginate library does not attempt to solve most of these problems; if the database adapter such as Active Record cannot handle paginated queries, the developer using will_paginate will have to find workarounds by tweaking the query or dropping down to the level of manually writing SQL.

  • The HTML output that this library generates is opinionated and includes links to previous & next page, first & last pages of results, as well as a selection of in-between pages. It does not render the full list of pages, since there might be hundreds. The will_paginate view helper offers some customization, but some developers would like to have finer-grained control over HTML output. Writing a custom link renderer for will_paginate is possible, but might not be trivial for all developers.

The will_paginate library is certainly a mature and stable solution, but also in a lot of ways dated: its design dates to the time of Rails 1.2 (this was in 2006) and it hasn't been keeping up with more modern ways of paginating through result sets nor newer database engines ever since. If some of the above concerns sound like they might be deal-breakers based on your use-case, you should consider using another libray or rolling your own approach.

In short: if all you need is a style of pagination where the user is offered a link to navigate to the next page of results (and nothing else), this library is likely not a good fit.