🦓

[Rails]turbo_streamとpagyで無限スクロールを実装する 2/2

2023/09/08に公開

はじめに

前回の記事を続きで、もっと見るボタンーなしの無限スクロールを実装していきたいと思います。

turbo_frameとpagyで無限スクロールを実装する

環境

Rails 7.0.7
ruby 3.2.1

流れ

前回と重なっている部分は飛ばします。

1. scaffoldとFakerでダミーデータを作成する
2. pagyをインストールする
3. 初期ファイルを作成する
4. 投稿にPagyを導入する ブログにPagyを導入する
5. ページネーションリンクを追加する Turbo Frameを使ってブログを読み込む
6. turbo_streamを使って新しい投稿内容をページの下にリロードせずに追加されるようにする
6-1. POSTリクエスト用URLを追加する
6-2. 「次のページがあればブログを読み込む」との条件を追加する
6-3. blogテンプレートファイルを作成する

scaffoldとFakerでダミーデータを作成する

ブログに無限スクロール追加するためにscaffoldでベースを作成し、Fakerでダミーデータを入れていきます。

bin/rails g scaffold blogs title body user:references
bin/rails db:migrate
db/seeds.rb
50.times do |i|
    title = "ブログ#{i + 1}"
    Blog.create(title: title, 
                body: Faker::Music.band, 
                user_id: User.first.id)
end
bin/rails db:seed

ブログにPagyを導入する

pagyのインストールと初期設定については前回の記事を参考にしてみてください。
ブログを10件ずつ表示させます。

app/controllers/blogs_controller.rb
class BlogsController < ApplicationController
...
  def index
+    @pagy, @blogs = pagy_countless(Blog.order(created_at: :desc), items: 10)
  end
end

pagyの無限スクロールモジュール:
https://ddnexus.github.io/pagy/docs/extras/support/

turbo_frame_tagで読み込まれた記事をロードする

次のページのブログコンテンツを非同期に読み込むためのTurbo Frame要素を生成します。

app/views/blogs/_next_page.html.erb
<%= turbo_frame_tag "blogs-page-#{@pagy.next}", 
	            loading: :lazy,
                    src: pagy_url_for(@pagy, @pagy.next) 
		    if @pagy.next.present? %>
app/views/blogs/index.html.erb
<%= render 'blogs/next_page' %>

"blogs-page-#{@pagy.next}":生成される<turbo-frame>要素のid属性を設定します。@pagy.next の値に基づいて、生成されるidは "blogs-page-2" のようなものになります。

loading: :lazy:フレームが遅延読み込みを使用することを指定します。遅延読み込みは、ユーザーのビューポート内にある時にフレーム内のコンテンツが読み込まれることを意味します。

src: pagy_url_for(@pagy, @pagy.next):フレームに非同期に読み込むコンテンツのソースURLを指定します。pagy_url_for メソッドはページネーションされたコンテンツのURLを生成し、@pagy.next は次のページのコンテンツを生成されます。

ブログの読み込みの条件を追加する

@pageがあればscrollable_blogs_listビューをレンダリングします。

app/controllers/blogs_controller.rb
class BlogsController < ApplicationController
...
  def index
    @pagy, @blogs = pagy_countless(Blog.order(created_at: :desc), items: 10)
+   render 'scrollable_blogs_list' if params[:page]    
  end
end

ブログビューを作成する

@pagy.pageは現在のページを表示させます。

app/views/scrollable_blogs_list.html.erb
<%= turbo_frame_tag "blogs-page-#{@pagy.page}" do %>
  <%= render @blogs %>
  <%= render 'blogs/next_page' %>
<% end %>

デベロッパーツールのネットワークタブでスクロールをするたびにブログをロードされていることを確認します。
Image from Gyazo

UXの向上に繋がるためLoading...などの文章やアニメーションを入れるのも良いかもしれないです。

終わりに

2回目の無限スクロールでした。
Turbo本当に便利ですね。
https://www.bearer.com/blog/infinite-scrolling-pagination-hotwire

Discussion