From 55d00fc40c8d1db1900492ffe5f7d61f05ece697 Mon Sep 17 00:00:00 2001 From: evazion Date: Wed, 8 Sep 2021 18:26:52 -0500 Subject: [PATCH] paginator: fix showing page 5000 when page count is unknown Fix a bug where if you did a slow search that took too long to calculate the page count, and you had 200 posts per page, then we would show page 5000 as the last page of the search. This was because we were artificially returning 1,000,000 as the post count to signal that the count timed out, but at 200 posts per page this would show 5000 as the last page of the search. --- app/components/paginator_component.rb | 2 +- app/logical/pagination_extension.rb | 8 +++++--- test/components/paginator_component_test.rb | 13 +++++++++++++ 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/app/components/paginator_component.rb b/app/components/paginator_component.rb index 41f0c562c..b82f654fb 100644 --- a/app/components/paginator_component.rb +++ b/app/components/paginator_component.rb @@ -27,7 +27,7 @@ class PaginatorComponent < ApplicationComponent ("..." unless left == 2), (left..right).to_a, ("..." unless right == last_page - 1), - (last_page unless last_page == 1), + (last_page unless last_page == 1 || last_page.infinite?), ].flatten.compact end diff --git a/app/logical/pagination_extension.rb b/app/logical/pagination_extension.rb index 7f875026f..8a8c83424 100644 --- a/app/logical/pagination_extension.rb +++ b/app/logical/pagination_extension.rb @@ -39,7 +39,7 @@ module PaginationExtension if count.present? @paginator_count = count elsif !search_count.nil? && search_count.blank? - @paginator_count = 1_000_000 + @paginator_count = Float::INFINITY end if page.to_s =~ /\Ab(\d+)\z/i @@ -138,15 +138,17 @@ module PaginationExtension end end + # Return the number of pages of results, or infinity if it takes too long to count. def total_pages + return Float::INFINITY if total_count.infinite? (total_count.to_f / records_per_page).ceil end - # taken from kaminari (https://github.com/amatsuda/kaminari) + # Return the number of results, or infinity if it takes too long to count. def total_count @paginator_count ||= unscoped.from(except(:offset, :limit, :order).reorder(nil)).count rescue ActiveRecord::StatementInvalid => e raise unless e.to_s =~ /statement timeout/ - @paginator_count ||= 1_000_000 + @paginator_count ||= Float::INFINITY end end diff --git a/test/components/paginator_component_test.rb b/test/components/paginator_component_test.rb index 5752669a6..33b9a291c 100644 --- a/test/components/paginator_component_test.rb +++ b/test/components/paginator_component_test.rb @@ -76,6 +76,19 @@ class PaginatorComponentTest < ViewComponent::TestCase assert_css("span", count: 3) end end + + context "for a search with an unknown number of pages" do + should "show the unlimited paginator" do + @tags = Tag.all + @tags.stubs(:total_count).returns(Float::INFINITY) + html = render_paginator(:numbered, @tags, page: 1, limit: 200) + + assert_css("span.paginator-current", text: "1") + assert_css("span.paginator-prev") + assert_css("a.paginator-next") + assert_css(".paginator a.paginator-page", count: 4, visible: :all) + end + end end end end