Class: GraphQL::Pagination::Connection

Inherits:
Object
  • Object
show all
Defined in:
lib/graphql/pagination/connection.rb

Overview

A Connection wraps a list of items and provides cursor-based pagination over it.

Connections were introduced by Facebook’s Relay front-end framework, but proved to be generally useful for GraphQL APIs. When in doubt, use connections to serve lists (like Arrays, ActiveRecord::Relations) via GraphQL.

Unlike the previous connection implementation, these default to bidirectional pagination.

Pagination arguments and context may be provided at initialization or assigned later (see Schema::Field::ConnectionExtension).

Direct Known Subclasses

ArrayConnection, RelationConnection

Defined Under Namespace

Classes: Edge, PaginationImplementationMissingError

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(items, context: nil, first: nil, after: nil, max_page_size: nil, last: nil, before: nil) ⇒ Connection

Returns a new instance of Connection.

Parameters:

  • items (Object)

    some unpaginated collection item, like an Array or ActiveRecord::Relation

  • context (Query::Context) (defaults to: nil)
  • first (Integer, nil) (defaults to: nil)

    The limit parameter from the client, if it provided one

  • after (String, nil) (defaults to: nil)

    A cursor for pagination, if the client provided one

  • last (Integer, nil) (defaults to: nil)

    Limit parameter from the client, if provided

  • before (String, nil) (defaults to: nil)

    A cursor for pagination, if the client provided one.

  • max_page_size (Integer, nil) (defaults to: nil)

    A configured value to cap the result size. Applied as first if neither first or last are given.



57
58
59
60
61
62
63
64
65
# File 'lib/graphql/pagination/connection.rb', line 57

def initialize(items, context: nil, first: nil, after: nil, max_page_size: nil, last: nil, before: nil)
  @items = items
  @context = context
  @first_value = first
  @after_value = after
  @last_value = last
  @before_value = before
  @max_page_size = max_page_size
end

Instance Attribute Details

#after_valueObject

Raw access to client-provided values. (max_page_size not applied to first or last.)



30
31
32
# File 'lib/graphql/pagination/connection.rb', line 30

def after_value
  @after_value
end

#before_valueObject

Raw access to client-provided values. (max_page_size not applied to first or last.)



30
31
32
# File 'lib/graphql/pagination/connection.rb', line 30

def before_value
  @before_value
end

#contextGraphQL::Query::Context



27
28
29
# File 'lib/graphql/pagination/connection.rb', line 27

def context
  @context
end

#firstInteger?

Returns A clamped first value. (The underlying instance variable doesn’t have limits on it.) If neither first nor last is given, but max_page_size is present, max_page_size is used for first.

Returns:

  • (Integer, nil)

    A clamped first value. (The underlying instance variable doesn’t have limits on it.) If neither first nor last is given, but max_page_size is present, max_page_size is used for first.



77
78
79
80
81
82
83
84
85
# File 'lib/graphql/pagination/connection.rb', line 77

def first
  @first ||= begin
    capped = limit_pagination_argument(@first_value, max_page_size)
    if capped.nil? && last.nil?
      capped = max_page_size
    end
    capped
  end
end

#first_valueObject

Raw access to client-provided values. (max_page_size not applied to first or last.)



30
31
32
# File 'lib/graphql/pagination/connection.rb', line 30

def first_value
  @first_value
end

#itemsObject (readonly)

Returns A list object, from the application. This is the unpaginated value passed into the connection.

Returns:

  • (Object)

    A list object, from the application. This is the unpaginated value passed into the connection.



24
25
26
# File 'lib/graphql/pagination/connection.rb', line 24

def items
  @items
end

#lastInteger?

Returns A clamped last value. (The underlying instance variable doesn’t have limits on it).

Returns:

  • (Integer, nil)

    A clamped last value. (The underlying instance variable doesn’t have limits on it)



89
90
91
# File 'lib/graphql/pagination/connection.rb', line 89

def last
  @last ||= limit_pagination_argument(@last_value, max_page_size)
end

#last_valueObject

Raw access to client-provided values. (max_page_size not applied to first or last.)



30
31
32
# File 'lib/graphql/pagination/connection.rb', line 30

def last_value
  @last_value
end

#max_page_sizeObject



68
69
70
# File 'lib/graphql/pagination/connection.rb', line 68

def max_page_size
  @max_page_size ||= context.schema.default_max_page_size
end

Class Method Details

.edge_classClass

Returns The class to use for wrapping items as edges { ... }. Defaults to Connection::Edge.

Returns:

  • (Class)

    The class to use for wrapping items as edges { ... }. Defaults to Connection::Edge



19
20
21
# File 'lib/graphql/pagination/connection.rb', line 19

def self.edge_class
  self::Edge
end

Instance Method Details

#afterString?

Returns the client-provided cursor. "" is treated as nil.

Returns:

  • (String, nil)

    the client-provided cursor. "" is treated as nil.



42
43
44
45
46
47
48
# File 'lib/graphql/pagination/connection.rb', line 42

def after
  if defined?(@after)
    @after
  else
    @after = @after_value == "" ? nil : @after_value
  end
end

#beforeString?

Returns the client-provided cursor. "" is treated as nil.

Returns:

  • (String, nil)

    the client-provided cursor. "" is treated as nil.



33
34
35
36
37
38
39
# File 'lib/graphql/pagination/connection.rb', line 33

def before
  if defined?(@before)
    @before
  else
    @before = @before_value == "" ? nil : @before_value
  end
end

#cursor_for(item) ⇒ String

Return a cursor for this item.

Parameters:

  • item (Object)

    one of the passed in #items, taken from #nodes

Returns:

  • (String)

Raises:



137
138
139
# File 'lib/graphql/pagination/connection.rb', line 137

def cursor_for(item)
  raise PaginationImplementationMissingError, "Implement #{self.class}#cursor_for(item) to return the cursor for #{item.inspect}"
end

#edge_nodesObject

Deprecated.

use #nodes instead

A dynamic alias for compatibility with Relay::BaseConnection.



105
106
107
# File 'lib/graphql/pagination/connection.rb', line 105

def edge_nodes
  nodes
end

#edgesArray<Edge>

Returns #nodes, but wrapped with Edge instances.

Returns:

  • (Array<Edge>)

    #nodes, but wrapped with Edge instances



94
95
96
# File 'lib/graphql/pagination/connection.rb', line 94

def edges
  @edges ||= nodes.map { |n| self.class.edge_class.new(n, self) }
end

#end_cursorString

Returns The cursor of the last item in #nodes.

Returns:

  • (String)

    The cursor of the last item in #nodes



130
131
132
# File 'lib/graphql/pagination/connection.rb', line 130

def end_cursor
  nodes.last && cursor_for(nodes.last)
end

#has_next_pageBoolean

Returns True if there are more items after this page.

Returns:

  • (Boolean)

    True if there are more items after this page

Raises:



115
116
117
# File 'lib/graphql/pagination/connection.rb', line 115

def has_next_page
  raise PaginationImplementationMissingError, "Implement #{self.class}#has_next_page to return the next-page check"
end

#has_previous_pageBoolean

Returns True if there were items before these items.

Returns:

  • (Boolean)

    True if there were items before these items

Raises:



120
121
122
# File 'lib/graphql/pagination/connection.rb', line 120

def has_previous_page
  raise PaginationImplementationMissingError, "Implement #{self.class}#has_previous_page to return the previous-page check"
end

#nodesArray<Object>

Returns A slice of #items, constrained by @first_value/@after_value/@last_value/@before_value.

Returns:

  • (Array<Object>)

    A slice of #items, constrained by @first_value/@after_value/@last_value/@before_value

Raises:



99
100
101
# File 'lib/graphql/pagination/connection.rb', line 99

def nodes
  raise PaginationImplementationMissingError, "Implement #{self.class}#nodes to paginate `@items`"
end

#page_infoObject

The connection object itself implements PageInfo fields



110
111
112
# File 'lib/graphql/pagination/connection.rb', line 110

def page_info
  self
end

#start_cursorString

Returns The cursor of the first item in #nodes.

Returns:

  • (String)

    The cursor of the first item in #nodes



125
126
127
# File 'lib/graphql/pagination/connection.rb', line 125

def start_cursor
  nodes.first && cursor_for(nodes.first)
end