[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