Paginating Plain Arrays and Enumerable Collections
Besides its deep integration with ORMs, will_paginate
provides a powerful utility for paginating any in-memory Array
or Enumerable collection. This is especially useful when dealing with data from external APIs, cached results, or any static list of items.
Array#paginate
The will_paginate/array
module extends Ruby's core Array
class with a paginate
method. The result is a WillPaginate::Collection
instance, which is an array-like object with additional pagination properties.
Usage
To use this feature, you may need to explicitly require it if you are not in a Rails environment where it's automatically loaded:
require 'will_paginate/array'
Now you can call paginate
on any array:
arr = ('a'..'z').to_a # An array of 26 letters
# Get the first page, with 5 items per page
paged_collection = arr.paginate(page: 1, per_page: 5)
paged_collection.length #=> 5
paged_collection #=> ['a', 'b', 'c', 'd', 'e']
# Get the second page
arr.paginate(page: 2, per_page: 5) #=> ['f', 'g', 'h', 'i', 'j']
# The collection knows its pagination state
paged_collection.total_entries #=> 26
paged_collection.total_pages #=> 6
Parameters
:page
: The current page number (defaults to 1).:per_page
: The number of items per page (defaults toWillPaginate.per_page
, which is 30).:total_entries
: The total number of items in the original array. By default, this is simplyself.length
, so you rarely need to specify it.
Manual Creation with WillPaginate::Collection
For more advanced use cases, you can manually construct a WillPaginate::Collection
. This gives you full control over creating a paginated collection from any data source, not just an existing array.
The WillPaginate::Collection.create
method is perfect for this. It takes the page, per_page, and total entries, and yields a new, empty collection object for you to populate.
Example
Imagine you are fetching data from a remote API that already provides pagination information.
require 'will_paginate/collection'
# Fictional API client
api_response = ApiClient.get_users(page: 2, per_page: 10)
# api_response.users => array of user data
# api_response.total_count => total number of users available
@users = WillPaginate::Collection.create(2, 10, api_response.total_count) do |pager|
# Populate the pager with the results for the current page
pager.replace(api_response.users)
end
# Now @users can be passed directly to the `will_paginate` view helper
# <%= will_paginate @users %>
This approach is powerful because it lets you adapt any data source to the API that the will_paginate
view helpers expect.