最近、Ruby on Railsで、APIの結果を無限スクロールで表示する画面を作成する機会があり、ページネーション用のGemを探していたところ「Pagy」を知りました。ページネーションのGemで有名なものは、「Kaminari」や「Will Pagenate」ですが、これらのGemに比べて「Pagy」はパフォーマンス面に重点をおいて開発されているとのことで、興味を持ち使ってみました。
目的
Pagyの公式ドキュメントはとても充実していますが、日本語の情報がまだ少なかったので、今回は「Pagy」の使用方法について記載していこうと思います。なお、パフォーマスについては、ベンチマークテストの結果がGithub上に掲載されていますので、興味のある方はそちらをご覧下さい。
やること
- Pagyを用いたページネーション
- Infinite-Scroll Pluginを用いた無限スクロール
データ
今回は、Modelから取得したデータではなく、APIレスポンスのデータをページネーションさせます。APIから受け取ったJSONデータをHashに変換後、配列形式でPagyへ渡すイメージです。なお、今回はPagyの利用が目的ですので、実際にAPIを用意することはせず、Controller内に配列データを直接定義します。
環境
本記事では、以下の環境を使用します。
- Ruby 2.4.1
- Rails 5.1.6
- Pagy 2.1.3
- Slim 4.0.1
Pagyのインストール
まずは、Gemfileに「pagy」を追加します。
gem 'pagy'
Gemを追加したら、インストールします。
bundle install --path vendor/bundle
Controllerの設定
ControllerにPagyのBackendモジュールをインクルードします。
class ContentsController < ApplicationController
include Pagy::Backend
end
Helperの設定
HelperにPagyのFrontendモジュールをインクルードします。
module ContentsHelper
include Pagy::Frontend
end
Pagyのイニシャライザファイル作成
イニシャライザファイルを作成することで、Pagyの設定をデフォルトから変更することができます。例えば、1ページに表示するデータ件数を指定したり、国際化対応の設定ができたりします。
今回は、配列に対してページネーションを行うために必要なライブラリの読み込みだけを行います。
その他の設定可能な項目については知りたい方は、Pagyのgithub上に公開されているので、そちらをご覧下さい。
require 'pagy/extras/array'
ページング処理の実装
配列をページング処理するには、pagy_arrayというメソッドに、ページング処理したい配列を渡し、その返り値をViewで使用します。なお、オプション引数としてハッシュを渡すことで、様々な指定をすることができます。下記サンプルの「items: 3」は1ページあたりの表示データ数を3つにすることを意味しています。オプション引数で指定できる内容は、Pagyのイニシャライザファイルで定義することも可能です。
上記でも説明したように、ページネーションさせるデータはdefine_dataメソッドとして、直接定義してます。
class ContentsController < ApplicationController
include Pagy::Backend
def search
@api_results = define_data
@pagy, @api_results = pagy_array(@api_results, items: 3)
end
def define_data
results = [
{ id: 1, content: 'test data 01', date: '2019/04/01 10:01:00' },
{ id: 2, content: 'test data 02', date: '2019/04/01 10:02:00' },
{ id: 3, content: 'test data 03', date: '2019/04/01 10:03:00' },
{ id: 4, content: 'test data 04', date: '2019/04/01 10:04:00' },
{ id: 5, content: 'test data 05', date: '2019/04/01 10:05:00' },
{ id: 6, content: 'test data 06', date: '2019/04/01 10:06:00' },
{ id: 7, content: 'test data 07', date: '2019/04/01 10:07:00' },
{ id: 8, content: 'test data 08', date: '2019/04/01 10:08:00' },
{ id: 9, content: 'test data 09', date: '2019/04/01 10:09:00' },
{ id: 10, content: 'test data 10', date: '2019/04/01 10:10:00' },
{ id: 11, content: 'test data 11', date: '2019/04/01 10:11:00' },
{ id: 12, content: 'test data 12', date: '2019/04/01 10:12:00' },
{ id: 13, content: 'test data 13', date: '2019/04/01 10:13:00' },
{ id: 14, content: 'test data 14', date: '2019/04/01 10:14:00' },
{ id: 15, content: 'test data 15', date: '2019/04/01 10:15:00' },
{ id: 16, content: 'test data 16', date: '2019/04/01 10:16:00' },
{ id: 17, content: 'test data 17', date: '2019/04/01 10:17:00' },
{ id: 18, content: 'test data 18', date: '2019/04/01 10:18:00' },
{ id: 19, content: 'test data 19', date: '2019/04/01 10:19:00' },
{ id: 20, content: 'test data 20', date: '2019/04/01 10:20:00' },
{ id: 21, content: 'test data 21', date: '2019/04/01 10:21:00' },
{ id: 22, content: 'test data 22', date: '2019/04/01 10:22:00' },
{ id: 23, content: 'test data 23', date: '2019/04/01 10:23:00' },
{ id: 24, content: 'test data 24', date: '2019/04/01 10:24:00' },
{ id: 25, content: 'test data 25', date: '2019/04/01 10:25:00' },
{ id: 26, content: 'test data 26', date: '2019/04/01 10:26:00' },
{ id: 27, content: 'test data 27', date: '2019/04/01 10:27:00' },
{ id: 28, content: 'test data 28', date: '2019/04/01 10:28:00' },
{ id: 29, content: 'test data 29', date: '2019/04/01 10:29:00' },
{ id: 30, content: 'test data 30', date: '2019/04/01 10:30:00' }
]
end
end
これでページングさせるデータの準備はできたので、次にビュー側の処理を書いていきます。なお、divタグの「contents」というIDと、「content」というclass名は任意ですが、無限スクロール実装時にJavaScript側で使用するので、変更する場合はご注意下さい。
# contents
.content
- @api_results.map do |result|
div
= "内容:#{result[:content]} | 作成日時:#{result[:date]} "
== pagy_nav @pagy
ページネーション 動作確認
ここまで実装すると、下記のようにページングが行えるようになっているはずです。
「2」や「3」、「Prev」、「Next」が機能することを確認しましょう。
無限スクロールの導入
作成したページングを無限スクロールへ変更していきます。
まずは、下記よりJavaScriptのプラグインを取得し、「app/assets/javascripts/」直下に配置します。
次に、無限スクロールを行うViewに対応するJavaScriptを作成します。
$(document).on('turbolinks:load', function () {
$('#contents').infiniteScroll({
path: "nav.pagination a[rel=next]",
append: ".content",
hideNav: '.pagination',
history: false,
prefill: true,
status: '.page-load-status'
})
});
指定しているオプションの意味は、下記の通りです。
- path: "nav.pagination a[rel=next]"・・・次のページへのリンクを指定
- append: ".content"・・・追加する要素を指定
- hideNav: '.pagination'・・・ページングのナビゲーションを非表示
- history: false・・・ページの変更ごとにブラウザの履歴とURLを変更しない
- prefill: true・・・初期化時にロードして、要素を追加
- status: '.page-load-status'・・・ページ読み込みの状態を示すステータス要素を表示
最後に、JQueryを読み込むように設定します。
//= require jquery
無限スクロール 動作確認
再度、画面を確認すると、無限スクロールが実現できているはずです。
うまく動かない場合は、Slimのインデント、divタグのIDやclass名を確認してみて下さい。
ソースコード
実際に手元でコードを動かしたい方は、下記よりcloneしてご使用下さい。