Using will_paginate with ActiveRecord
The primary integration for will_paginate is with ActiveRecord, the default ORM for Ruby on Rails. It extends ActiveRecord::Base and ActiveRecord::Relation to provide simple and chainable pagination methods.
The .paginate() Method
The main method is .paginate(). It's a paginating finder that works similarly to ActiveRecord's own finders. It returns a relation that is aware of its pagination state.
Parameters
:page(required): The current page number to retrieve. Usuallyparams[:page].:per_page: The number of records to retrieve per page. This overrides any model-level or global settings.:total_entries: Manually sets the total number of records. This is useful for performance, as it skips theCOUNTquery thatwill_paginatewould otherwise perform.
Example
# Get the first page with 20 posts per page
@posts = Post.paginate(page: params[:page], per_page: 20)
# Get page 3, letting the model/global setting define per_page
@users = User.paginate(page: 3)
The .page() Shorthand
For a more modern, chainable syntax that integrates cleanly with other ActiveRecord scopes, use the .page() method.
# Chainable and clean
@posts = Post.where(published: true).page(params[:page]).order(id: :desc)
You can set the number of items per page by chaining .per_page() or .limit():
@posts = Post.page(params[:page]).per_page(5)
@posts = Post.page(params[:page]).limit(5) # `limit` is an alias for per_page
Returned Collection
Both .paginate() and .page() return an ActiveRecord::Relation instance that has been extended with WillPaginate::Collection methods. This means you can iterate over it just like a regular collection of records, but you also have access to helpful pagination attributes:
collection.current_pagecollection.per_pagecollection.total_entriescollection.total_pagescollection.offsetcollection.previous_pagecollection.next_page
Advanced Querying
will_paginate works seamlessly with most advanced ActiveRecord queries.
Scopes and Associations
# Paginate results from a scope
@poor_developers = Developer.poor.paginate(page: 1)
# Paginate an association
@project = Project.find(1)
@developers = @project.developers.paginate(page: 1)
Joins
You can paginate queries that include joins.
@developers = Developer.joins(:projects)
.where('projects.id = ?', 1)
.paginate(page: 1)
Grouping
Pagination with grouped queries is also supported. will_paginate is smart enough to correctly calculate the total number of entries.
@salaries = Developer.select('salary').group('salary').page(1)
# This will correctly count the number of groups, not the total number of developers.
@salaries.total_entries # => 4 (for example)
Custom SQL with paginate_by_sql
For complex queries where ActiveRecord's query interface isn't sufficient, you can use paginate_by_sql. This method takes a raw SQL string and paginates the results by adding the appropriate LIMIT and OFFSET clauses.
sql = "SELECT * FROM topics WHERE content LIKE '%ruby%'"
@topics = Topic.paginate_by_sql(sql, page: params[:page], per_page: 10)
will_paginate will attempt to generate a COUNT query automatically. If this fails or you want to optimize it, you can provide a :total_entries option.