I have the pleasure to introduce you to a new gem created to support a JSON:API-based web applications. Standalone pagination support.

Why another pagination gem?

Well, I know what are you thinking - WHY I bothered to build another pagination gem? There are plenty of pagination plugins for ruby web applications out there, to list just a few popular ones:

The first two are “kaminari” and “will_paginate”. Both are closely tight to ActiveRecord which can be a good or bad thing depending on your needs. For sure, implementing any of those above is extremely easy as they just extend your models!

However, they have two big issues.

  1. It’s super hard to use them out of the ActiveRecord-based collections.
  2. They are slow.

Fortunately, smart people out there already addressed both of those problems and invented Pagy.

Pagy is a much more attractive gem, as it’s dozens of times faster than any of the solutions listed above and really framework-agnostic. It can be used in any Rack applications and I use it (directly or indirectly) in all my projects no matter what framework I play with.

However, It also comes with at least 2 issues I think are important.

1. The architectural flaws

First of the issues I’ve faced is that Pagy based on modules and a lot of assumptions that forces the user to do a lot of configuration in case she wants to use the gem outside of standard Rails-Based controllers.

For example, pagy assumes that there is a params method accessible in the class you include the Pagy::Backend module. If we want to add metadata and related link information, we need to require an extension which also needs to be included, but this one assumes, we have a request method accessible!

All that is not a problem if we want to use it inside of Rails applications, but it generates issues in case of more fancy use cases.

The JSON:API support

The other issue is, that as this gem is so framework-agnostic, there is always a bit of code you’d need to write to make it compatible with JSON:API standard. As JSON:API suggests to control your pagination using a nested query parameter page[size] and page[number], The pagy gem needs to be adjusted in order to use it effectively.

The JSOM:Pagination

To solve both of the issues listed above, I’ve decided to write a tiny wrapper around pagy, to deliver a convenient experience for any JSON API-compatible app - and named it: jsom-pagination.

JSOM:Pagination is a simple class that we can use in any place of the application (not only in the controllers!) - and in any kind of ruby application.

Here are two examples how to use it in your app.

First you need to instantiate the instance of a paginator:

require 'jsom-pagination'
paginator = JSOM::Pagination::Paginator.new

And to paginate an array you just need to call it with a collection, parameters hash and the base URL value:

collection = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
pagination_params = { number: 2, size: 3 }
paginated = paginator.call(collection, params: pagination_params, base_url: 'https://example.com')

So what is the cool thing about it?

It may not look amazing at the start, but injecting the dependencies into the paginator allows us to run the pagination everywhere easily. Also, the JSON:API support is built in.

All the meta information is accessible right away:

paginated.meta
# => #<JSOM::Pagination::MetaData total=10 pages=4>

The same applies to links to the related pages.

Summary

Writing useful gems is not a trivial thing. But in Ruby world, I see things often overcomplicated and assuming too much. It’s surprising that such a simple problem as pagination generates so many issues during the implementation and usage of the suggested solutions.

I hope that jsom-pagination will help you go around them!