switch to pagy for pagination

This commit is contained in:
2026-02-03 21:21:53 +01:00
parent f35a09f07a
commit a139bde102
9 changed files with 32 additions and 17 deletions
+3
View File
@@ -47,6 +47,9 @@ gem "thruster", require: false
# Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images]
gem "image_processing", "~> 1.2"
# Pagination [https://github.com/ddnexus/pagy]
gem "pagy", "~> 8.0"
group :development, :test do
# See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
gem "debug", platforms: %i[ mri windows ], require: "debug/prelude"
+3
View File
@@ -232,6 +232,7 @@ GEM
nokogiri (1.19.0-x86_64-linux-gnu)
racc (~> 1.4)
ostruct (0.6.3)
pagy (8.6.3)
parallel (1.27.0)
parser (3.3.10.1)
ast (~> 2.4.1)
@@ -430,6 +431,7 @@ DEPENDENCIES
importmap-rails
jbuilder
kamal
pagy (~> 8.0)
propshaft
puma (>= 5.0)
rails (~> 8.1.2)
@@ -531,6 +533,7 @@ CHECKSUMS
nio4r (2.7.5) sha256=6c90168e48fb5f8e768419c93abb94ba2b892a1d0602cb06eef16d8b7df1dca1
nokogiri (1.19.0-x86_64-linux-gnu) sha256=f482b95c713d60031d48c44ce14562f8d2ce31e3a9e8dd0ccb131e9e5a68b58c
ostruct (0.6.3) sha256=95a2ed4a4bd1d190784e666b47b2d3f078e4a9efda2fccf18f84ddc6538ed912
pagy (8.6.3) sha256=537b2ee3119f237dd6c4a0d0a35c67a77b9d91ebb9d4f85e31407c2686774fb2
parallel (1.27.0) sha256=4ac151e1806b755fb4e2dc2332cbf0e54f2e24ba821ff2d3dcf86bf6dc4ae130
parser (3.3.10.1) sha256=06f6a725d2cd91e5e7f2b7c32ba143631e1f7c8ae2fb918fc4cebec187e6a688
pp (0.6.3) sha256=2951d514450b93ccfeb1df7d021cae0da16e0a7f95ee1e2273719669d0ab9df6
@@ -1,5 +1,6 @@
class ApplicationController < ActionController::Base
include BotBlocker
include Pagy::Backend
# Changes to the importmap will invalidate the etag for HTML responses
stale_when_importmap_changes
+2 -5
View File
@@ -6,8 +6,6 @@ class EntriesController < ApplicationController
@category = params[:category].presence
@query = params[:q].to_s.strip
@starts_with = params[:starts_with].presence
@page = [ params[:page].to_i, 1 ].max
@per_page = 25
entries_scope = Entry.active_entries
entries_scope = entries_scope.with_category(@category)
@@ -16,9 +14,8 @@ class EntriesController < ApplicationController
entries_scope = entries_scope.alphabetical_for(@language_code) if @query.blank? && @starts_with.blank? && @language_code.present?
entries_scope = entries_scope.order(created_at: :desc) if entries_scope.order_values.empty?
@total_entries = entries_scope.count
@total_pages = (@total_entries.to_f / @per_page).ceil
@entries = entries_scope.offset((@page - 1) * @per_page).limit(@per_page)
@pagy, @entries = pagy(entries_scope, items: 25)
@total_entries = @pagy.count
@entry_count = Entry.active_entries.count
@requested_count = Entry.requested.count
+2
View File
@@ -1,4 +1,6 @@
module ApplicationHelper
include Pagy::Frontend
def language_name(code)
supported_languages.find { |l| l.code == code }&.name
end
+12 -10
View File
@@ -86,17 +86,19 @@
</div>
<div class="flex items-center justify-between mt-4 text-sm text-slate-600">
<div>Page <%= @page %> of <%= [@total_pages, 1].max %></div>
<div><%= pagy_info(@pagy) %></div>
<div class="flex items-center gap-2">
<% previous_page = @page > 1 ? @page - 1 : nil %>
<% next_page = @page < @total_pages ? @page + 1 : nil %>
<% pagination_params = { q: @query.presence, category: @category.presence, language: @language_code.presence, starts_with: @starts_with.presence }.compact %>
<%= link_to "Previous", previous_page ? entries_path(pagination_params.merge(page: previous_page)) : "#",
class: "px-3 py-1.5 rounded-md border border-slate-200 #{previous_page ? 'hover:border-indigo-300' : 'text-slate-300 cursor-not-allowed'}",
data: { turbo_stream: true } %>
<%= link_to "Next", next_page ? entries_path(pagination_params.merge(page: next_page)) : "#",
class: "px-3 py-1.5 rounded-md border border-slate-200 #{next_page ? 'hover:border-indigo-300' : 'text-slate-300 cursor-not-allowed'}",
data: { turbo_stream: true } %>
<%
pagination_params = { q: @query.presence, category: @category.presence, language: @language_code.presence, starts_with: @starts_with.presence }.compact
prev_url = @pagy.prev ? entries_path(pagination_params.merge(page: @pagy.prev)) : nil
next_url = @pagy.next ? entries_path(pagination_params.merge(page: @pagy.next)) : nil
%>
<%= link_to "Previous", prev_url || "#",
class: "px-3 py-1.5 rounded-md border border-slate-200 #{'opacity-50 pointer-events-none' unless prev_url}",
data: (prev_url ? { turbo_stream: true } : {}) %>
<%= link_to "Next", next_url || "#",
class: "px-3 py-1.5 rounded-md border border-slate-200 #{'opacity-50 pointer-events-none' unless next_url}",
data: (next_url ? { turbo_stream: true } : {}) %>
</div>
</div>
</div>
+6
View File
@@ -0,0 +1,6 @@
# Pagy Configuration
require "pagy/extras/overflow"
Pagy::DEFAULT[:items] = 25 # Match current 25 items per page
Pagy::DEFAULT[:page_param] = :page
Pagy::DEFAULT[:overflow] = :last_page
+2 -1
View File
@@ -41,7 +41,8 @@ class EntriesControllerTest < ActionDispatch::IntegrationTest
test "should paginate results" do
get entries_url, params: { page: 2 }
assert_response :success
assert_select "div", text: /Page 2 of/i
assert_not_nil assigns(:pagy)
assert_select "div", text: /Displaying/i
end
test "should handle invalid language code" do
+1 -1
View File
@@ -102,7 +102,7 @@ class PublicBrowsingTest < ApplicationSystemTestCase
visit root_path
assert_selector ".entry-row", count: 25
assert_link "2"
assert_link "Next"
end
test "visitor sees entry statistics" do