Welcome to mirror list, hosted at ThFree Co, Russian Federation.

active_record_array_connection.rb « pagination « graphql « gitlab « lib - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 9e40f79b2fde12234a0da90d934b9fdb78244244 (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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# 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