blob: 99b125cc2a092715e2a214a690d0644ac1d6d236 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
# frozen_string_literal: true
module Gitlab
module Pagination
module Keyset
class Pager
attr_reader :request
def initialize(request)
@request = request
end
def paginate(relation)
# Validate assumption: The last two columns must match the page order_by
validate_order!(relation)
# This performs the database query and retrieves records
# We retrieve one record more to check if we have data beyond this page
all_records = relation.limit(page.per_page + 1).to_a # rubocop: disable CodeReuse/ActiveRecord
records_for_page = all_records.first(page.per_page)
# If we retrieved more records than belong on this page,
# we know there's a next page
there_is_more = all_records.size > records_for_page.size
apply_headers(records_for_page.last, there_is_more)
records_for_page
end
private
def apply_headers(last_record_in_page, there_is_more)
end_reached = last_record_in_page.nil? || !there_is_more
lower_bounds = last_record_in_page&.slice(page.order_by.keys)
next_page = page.next(lower_bounds, end_reached)
request.apply_headers(next_page)
end
def page
@page ||= request.page
end
def validate_order!(rel)
present_order = rel.order_values.map { |val| [val.expr.name.to_sym, val.direction] }.last(2).to_h
unless page.order_by == present_order
raise ArgumentError, "Page's order_by does not match the relation's order: #{present_order} vs #{page.order_by}"
end
end
end
end
end
end
|