More-style pagination for Rails. As an example, consider the following story:
- There are 175 posts in the database.
- User visits the posts index page; the first 10 posts are listed.
- User clicks a "More posts" link; the next 20 posts are appended to the list (30 total) without refreshing the page.
- User clicks the "More posts" link again; the next 30 posts are appended to the list (60 total) without refreshing the page.
- User clicks the "More posts" link again; the browser navigates to a new page listing the next 60 posts.
- User clicks a "More posts" link; the browser navigates to a new page listing the final 55 posts. No "More posts" link is rendered.
- At any point the user can manually refresh the page, and the same set of posts will be shown. Likewise, the page can navigated away from and back to, or bookmarked and returned to later, and the same set of posts will be shown. (Assuming the database remains unchanged.)
- If JavaScript is disabled, the first and second "More posts" links will simply navigate to a new page listing only the posts that would have been fetched via Ajax.
With moar, this story can be realized using the following code:
## app/controllers/posts_controller.rb
class PostsController < ApplicationController
# Step 1 (optional): set controller-specific pagination increments
moar_increments [10, 20, 30]
def index
# Step 2: apply pagination increments
@posts = moar(Post).order(:created_at)
end
end
<!-- app/views/posts/index.html.erb -->
<h1>Posts</h1>
<ul id="list-of-posts">
<% @posts.each do |post| %>
<li><%= link_to post.title, post %></li>
<% end %>
</ul>
<!-- Step 3: render pagination link -->
<%= link_to_more @posts, "#list-of-posts" %>
A few things to note:
- No special code is required to perform the fetch and render of incremental paginated results via Ajax.
- The maximum number of results per page (60, in this example) is the sum of all pagination increments (10 + 20 + 30).
- The
link_to_more
helper automatically infers the link text ("More posts") from the paginated results. This can be configured; see the Configuration section below. - The second argument of the
link_to_more
helper is a CSS selector which points to the paginated results container element. Results fetched via Ajax are appended directly to that element, so the selector must point to the rendered results' immediate container. For example, if the paginated results are rendered as rows in a table, the selector should point to the<tbody>
element rather than the<table>
element. - The
link_to_more
helper will render nothing when there are no more paginated results — noif
required.
For complete usage details, see the documentation for
moar_increments
,
moar
, and
link_to_more
.
The moar install generator will create two configuration files in your project directory: "config/initializers/moar.rb" and "config/locales/moar.en.yml".
"config/initializers/moar.rb" can be edited to change the default
pagination increments used when moar_increments
is not called, and to
change the query param used to indicate page number.
"config/locales/moar.en.yml" can be edited to change the link text
rendered by link_to_more
. Translations listed in this file are
provided a results_name
interpolation argument which contains the
humanized translated pluralized downcased name of the relevant model.
For example, if the translation string is "Need more %{results_name}!"
and the paginated results consist of CowBell
models, the rendered text
will be "Need more cow bells!".
Add the gem to your Gemfile:
$ bundle add moar
And run the installation generator:
$ rails generate moar:install
Run bin/test
to run the tests.