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.
This commit is contained in:
evazion
2021-09-08 18:26:52 -05:00
parent 668dd50ea8
commit 55d00fc40c
3 changed files with 19 additions and 4 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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