91 lines
2.3 KiB
Ruby
91 lines
2.3 KiB
Ruby
|
# frozen_string_literal: true
|
||
|
|
||
|
# Connection for an array of Active Record instances.
|
||
|
# Resolvers needs to handle cursors (before and after).
|
||
|
# This connection will handle (first and last).
|
||
|
# Supports batch loaded items.
|
||
|
# Expects the array to use a fixed DESC order. This is similar to
|
||
|
# ExternallyPaginatedArrayConnection.
|
||
|
module Gitlab
|
||
|
module Graphql
|
||
|
module Pagination
|
||
|
class ActiveRecordArrayConnection < GraphQL::Pagination::ArrayConnection
|
||
|
include ::Gitlab::Graphql::ConnectionCollectionMethods
|
||
|
prepend ::Gitlab::Graphql::ConnectionRedaction
|
||
|
|
||
|
delegate :<<, to: :items
|
||
|
|
||
|
def nodes
|
||
|
load_nodes
|
||
|
|
||
|
@nodes
|
||
|
end
|
||
|
|
||
|
def next_page?
|
||
|
load_nodes
|
||
|
|
||
|
if before
|
||
|
true
|
||
|
elsif first
|
||
|
limit_value < items.size
|
||
|
else
|
||
|
false
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def previous_page?
|
||
|
load_nodes
|
||
|
|
||
|
if after
|
||
|
true
|
||
|
elsif last
|
||
|
limit_value < items.size
|
||
|
else
|
||
|
false
|
||
|
end
|
||
|
end
|
||
|
|
||
|
# see https://graphql-ruby.org/pagination/custom_connections#connection-wrapper
|
||
|
alias_method :has_next_page, :next_page?
|
||
|
alias_method :has_previous_page, :previous_page?
|
||
|
|
||
|
def cursor_for(item)
|
||
|
# item could be a batch loaded item. Sync it to have the id.
|
||
|
cursor = { 'id' => Gitlab::Graphql::Lazy.force(item).id.to_s }
|
||
|
encode(cursor.to_json)
|
||
|
end
|
||
|
|
||
|
# Part of the implied interface for default objects for BatchLoader: objects must be clonable
|
||
|
def dup
|
||
|
self.class.new(
|
||
|
items.dup,
|
||
|
first: first,
|
||
|
after: after,
|
||
|
max_page_size: max_page_size,
|
||
|
last: last,
|
||
|
before: before
|
||
|
)
|
||
|
end
|
||
|
|
||
|
private
|
||
|
|
||
|
def limit_value
|
||
|
# note: only first _or_ last can be specified, not both
|
||
|
@limit_value ||= [first, last, max_page_size].compact.min
|
||
|
end
|
||
|
|
||
|
def load_nodes
|
||
|
@nodes ||= begin
|
||
|
limited_nodes = items
|
||
|
|
||
|
limited_nodes = limited_nodes.first(first) if first
|
||
|
limited_nodes = limited_nodes.last(last) if last
|
||
|
|
||
|
limited_nodes
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|