[Rails]turbo_streamとpagyで無限スクロールを実装する 1/2
はじめに
turbo_streamとpagyを使って無限スクロールを実装していきます。
環境
Rails 7.0.7
ruby 3.2.1
流れ
1. Fakerでダミーデータを作成する
2. pagyをインストールする
3. 初期ファイルを作成する
4. 投稿にPagyを導入する
5. ページネーションリンクを追加する
6. turbo_streamを使って新しい投稿内容をページの下にリロードせずに追加されるようにする
6-1. POSTリクエスト用URLを追加する
6-2. もっと見るボタンを作成する
6-3. turbo_streamパーシャルを作成し、取得された投稿をパーシャル内に表示させる
Fakerを使ってダミーデータを作成する
投稿を100件作成します。
100.times do |i|
title = "タイトル#{i + 1}"
Post.create(title: title,
body: Faker::Quote.famous_last_words,
user_id: User.first.id)
end
bin/rails db:seed
Pagyをインストールする
gem 'pagy'
bundle install
Pagyをインクルードする
class ApplicationController < ActionController::Base
include Pagy::Backend
end
module ApplicationHelper
include Pagy::Frontend
end
無限スクロール用初期ファイルを作成する
config/initilizers/ディレクトリ内pagy.rbを作成し、無限スクロール用モジュールを導入します。
require 'pagy/extras/countless'
ドキュメントを参考して進めていきます。
サーバーを再起動します。
投稿にPagyを導入する
投稿をページごとに10件ずつ表示するようにします。
class TodosController < ApplicationController
...
def index
@pagy, @posts = pagy_countless(Post.includes(:user).order(created_at: :desc), items: 10)
end
end
ビューにページネーションリンクを追加する
<%== pagy_next_link(@pagy, text: 'More...', link_extra: 'id="next_link"') %>
ここでページネーションを実装されたことを確認します。URLがposts?page=1、posts?page=2...になっています。
現状ページをリロードして新しい投稿を取得していますが、turbo_streamを使って非同期に投稿コンテンツを取得しページを動的に更新していきます。
POSTリクエスト用URLを追加する
resources :posts do
collection do
post :index
end
end
コントローラーにturboリスポンスに対応するコードも追加します。
class TodosController < ApplicationController
def index
...
respond_to do |format|
format.turbo_stream
format.html
end
end
end
もっと見るボタンを作成する
デフォルトのリンクを書き換えて投稿の下に追加します。
<%= link_to 'もっと見る', pagy_url_for(@pagy, @pagy.next) %>

pagy_url_for
pagy_url_forはPagyのヘルパーメソッドで、ページネーションリンクのURLを生成するために使用されます。通常、ページネーションのリンクをカスタマイズする必要がある場合に使います。
pagy_url_for(pagy, page)
-
pagy: Pagyオブジェクトです。通常、コントローラーアクション内でpagyメソッドを使用して生成されたものを渡します。 -
page: リンクを生成するページ番号を指定します。これは通常、ページネーションリンクを生成するためのリンク先ページの番号です。
index.turbo_stream.erbパーシャルを作成する
<%= turbo_stream.append "posts" do %>
<%= render @posts %>
<% end %>
<%= turbo_stream.replace "load_more_btn" do %>
<%= link_to 'もっと見る', pagy_url_for(@pagy, @pagy.next), data: { turbo_method: :post } %>
<% end %>
_load_more_btn.html.erbパーシャルを作成した方が良いですが、テストのために投稿の下に直接書いてます。
問題なさそうですが、投稿ない場合もっと見るボタンーを非表示にさせたいのでif文を追加します。
<%= turbo_stream.replace "load_more_btn" do %>
<%= link_to 'もっと見る', pagy_url_for(@pagy, @pagy.next),
data: { turbo_method: :post }
+ if @pagy.next.present? %>
<% end %>
終わりに
turbo_streamとpagyによる無限スクロールでした。
ボタン無しのパターンもまとめましたので良かったら参考にしてみてください。
参考した記事:


Discussion