class GraphQL::Pagination::Connection
Pagination arguments and context may be provided at initialization or assigned later (see {Schema::Field::ConnectionExtension}).
Unlike the previous connection implementation, these default to bidirectional pagination.
to serve lists (like Arrays, ActiveRecord::Relations) via GraphQL.
proved to be generally useful for GraphQL APIs. When in doubt, use connections
Connections were introduced by Facebook’s ‘Relay` front-end framework, but
A Connection wraps a list of items and provides cursor-based pagination over it.
def self.edge_class
-
(Class)
- The class to use for wrapping items as `edges { ... }`. Defaults to `Connection::Edge`
def self.edge_class self::Edge end
def after
-
(String, nil)
- the client-provided cursor. `""` is treated as `nil`.
def after if defined?(@after) @after else @after = @after_value == "" ? nil : @after_value end end
def before
-
(String, nil)
- the client-provided cursor. `""` is treated as `nil`.
def before if defined?(@before) @before else @before = @before_value == "" ? nil : @before_value end end
def cursor_for(item)
-
(String)
-
Parameters:
-
item
(Object
) -- one of the passed in {items}, taken from {nodes}
def cursor_for(item) raise PaginationImplementationMissingError, "Implement #{self.class}#cursor_for(item) to return the cursor for #{item.inspect}" end
def decode(cursor)
def decode(cursor) context.schema.cursor_encoder.decode(cursor, nonce: true) end
def edge_nodes
- use {#nodes} instead
def edge_nodes nodes end
def edges
-
(Array
- {nodes}, but wrapped with Edge instances)
def edges @edges ||= nodes.map { |n| self.class.edge_class.new(n, self) } end
def encode(cursor)
def encode(cursor) context.schema.cursor_encoder.encode(cursor, nonce: true) end
def end_cursor
-
(String)
- The cursor of the last item in {nodes}
def end_cursor nodes.last && cursor_for(nodes.last) end
def first
-
(Integer, nil)
-
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
def has_max_page_size_override?
def has_max_page_size_override? @has_max_page_size_override end
def has_next_page
-
(Boolean)
- True if there are more items after this page
def has_next_page raise PaginationImplementationMissingError, "Implement #{self.class}#has_next_page to return the next-page check" end
def has_previous_page
-
(Boolean)
- True if there were items before these items
def has_previous_page raise PaginationImplementationMissingError, "Implement #{self.class}#has_previous_page to return the previous-page check" end
def initialize(items, context: nil, first: nil, after: nil, max_page_size: :not_given, last: nil, before: nil)
-
max_page_size
(Integer, nil
) -- A configured value to cap the result size. Applied as `first` if neither first or last are given. -
before
(String, nil
) -- A cursor for pagination, if the client provided one. -
last
(Integer, nil
) -- Limit parameter from the client, if provided -
after
(String, nil
) -- A cursor for pagination, if the client provided one -
first
(Integer, nil
) -- The limit parameter from the client, if it provided one -
context
(Query::Context
) -- -
items
(Object
) -- some unpaginated collection item, like an `Array` or `ActiveRecord::Relation`
def initialize(items, context: nil, first: nil, after: nil, max_page_size: :not_given, last: nil, before: nil) @items = items @context = context @first_value = first @after_value = after @last_value = last @before_value = before # This is only true if the object was _initialized_ with an override # or if one is assigned later. @has_max_page_size_override = max_page_size != :not_given @max_page_size = if max_page_size == :not_given nil else max_page_size end end
def last
-
(Integer, nil)
- A clamped `last` value. (The underlying instance variable doesn't have limits on it)
def last @last ||= limit_pagination_argument(@last_value, max_page_size) end
def limit_pagination_argument(argument, max_page_size)
-
(nil, Integer)
- `nil` if the input was `nil`, otherwise a value between `0` and `max_page_size`
Parameters:
-
max_page_size
(nil, Integer
) -- -
argument
(nil, Integer
) -- `first` or `last`, as provided by the client
def limit_pagination_argument(argument, max_page_size) if argument if argument < 0 argument = 0 elsif max_page_size && argument > max_page_size argument = max_page_size end end argument end
def max_page_size
def max_page_size if @has_max_page_size_override @max_page_size else context.schema.default_max_page_size end end
def max_page_size=(new_value)
def max_page_size=(new_value) @has_max_page_size_override = true @max_page_size = new_value end
def nodes
-
(Array
- A slice of {items}, constrained by {@first_value}/{@after_value}/{@last_value}/{@before_value}
def nodes raise PaginationImplementationMissingError, "Implement #{self.class}#nodes to paginate `@items`" end
def page_info
def page_info self end
def start_cursor
-
(String)
- The cursor of the first item in {nodes}
def start_cursor nodes.first && cursor_for(nodes.first) end