Class: GraphQL::Pagination::Connection
- Inherits:
-
Object
- Object
- GraphQL::Pagination::Connection
- 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
Defined Under Namespace
Classes: Edge, PaginationImplementationMissingError
Instance Attribute Summary collapse
-
#after_value ⇒ Object
Raw access to client-provided values.
-
#arguments ⇒ Hash<Symbol => Object>
The field arguments from the field that returned this connection.
-
#before_value ⇒ Object
Raw access to client-provided values.
- #context ⇒ GraphQL::Query::Context
-
#edge_class ⇒ Class
A wrapper class for edges of this connection.
-
#field ⇒ GraphQL::Schema::Field
The field this connection was returned by.
-
#first ⇒ Integer?
A clamped
first
value. -
#first_value ⇒ Object
Raw access to client-provided values.
-
#items ⇒ Object
readonly
A list object, from the application.
-
#last ⇒ Integer?
A clamped
last
value. -
#last_value ⇒ Object
Raw access to client-provided values.
-
#parent ⇒ Object
The object this collection belongs to.
Instance Method Summary collapse
-
#after ⇒ String?
The client-provided cursor.
-
#before ⇒ String?
The client-provided cursor.
-
#cursor_for(item) ⇒ String
Return a cursor for this item.
- #default_page_size ⇒ Object
- #default_page_size=(new_value) ⇒ Object
-
#edge_nodes ⇒ Object
deprecated
Deprecated.
use #nodes instead
-
#edges ⇒ Array<Edge>
#nodes, but wrapped with Edge instances.
-
#end_cursor ⇒ String
The cursor of the last item in #nodes.
- #has_default_page_size_override? ⇒ Boolean
- #has_max_page_size_override? ⇒ Boolean
-
#has_next_page ⇒ Boolean
True if there are more items after this page.
-
#has_previous_page ⇒ Boolean
True if there were items before these items.
-
#initialize(items, parent: nil, field: nil, context: nil, first: nil, after: nil, max_page_size: NOT_CONFIGURED, default_page_size: NOT_CONFIGURED, last: nil, before: nil, edge_class: nil, arguments: nil) ⇒ Connection
constructor
A new instance of Connection.
- #max_page_size ⇒ Object
- #max_page_size=(new_value) ⇒ Object
-
#nodes ⇒ Array<Object>
A slice of #items, constrained by @first_value/@after_value/@last_value/@before_value.
-
#page_info ⇒ Object
The connection object itself implements
PageInfo
fields. -
#range_add_edge(item) ⇒ Edge
This is called by
Relay::RangeAdd
-- it can be overridden whenitem
needs some modifications based on this connection's state. -
#start_cursor ⇒ String
The cursor of the first item in #nodes.
- #was_authorized_by_scope_items? ⇒ Boolean
Constructor Details
#initialize(items, parent: nil, field: nil, context: nil, first: nil, after: nil, max_page_size: NOT_CONFIGURED, default_page_size: NOT_CONFIGURED, last: nil, before: nil, edge_class: nil, arguments: nil) ⇒ Connection
Returns a new instance of Connection.
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/graphql/pagination/connection.rb', line 69 def initialize(items, parent: nil, field: nil, context: nil, first: nil, after: nil, max_page_size: NOT_CONFIGURED, default_page_size: NOT_CONFIGURED, last: nil, before: nil, edge_class: nil, arguments: nil) @items = items @parent = parent @context = context @field = field @first_value = first @after_value = after @last_value = last @before_value = before @arguments = arguments @edge_class = edge_class || self.class::Edge # 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_CONFIGURED @max_page_size = if max_page_size == NOT_CONFIGURED nil else max_page_size end @has_default_page_size_override = default_page_size != NOT_CONFIGURED @default_page_size = if default_page_size == NOT_CONFIGURED nil else default_page_size end @was_authorized_by_scope_items = end |
Instance Attribute Details
#after_value ⇒ Object
Raw access to client-provided values. (max_page_size
not applied to first or last.)
36 37 38 |
# File 'lib/graphql/pagination/connection.rb', line 36 def after_value @after_value end |
#arguments ⇒ Hash<Symbol => Object>
Returns The field arguments from the field that returned this connection.
57 58 59 |
# File 'lib/graphql/pagination/connection.rb', line 57 def arguments @arguments end |
#before_value ⇒ Object
Raw access to client-provided values. (max_page_size
not applied to first or last.)
36 37 38 |
# File 'lib/graphql/pagination/connection.rb', line 36 def before_value @before_value end |
#context ⇒ GraphQL::Query::Context
22 23 24 |
# File 'lib/graphql/pagination/connection.rb', line 22 def context @context end |
#edge_class ⇒ Class
Returns A wrapper class for edges of this connection.
174 175 176 |
# File 'lib/graphql/pagination/connection.rb', line 174 def edge_class @edge_class end |
#field ⇒ GraphQL::Schema::Field
Returns The field this connection was returned by.
177 178 179 |
# File 'lib/graphql/pagination/connection.rb', line 177 def field @field end |
#first ⇒ Integer?
Returns A clamped first
value.
(The underlying instance variable doesn't have limits on it.)
If neither first
nor last
is given, but default_page_size
is
present, default_page_size is used for first. If default_page_size
is greater than max_page_size
, it'll be clamped down to
max_page_size. If
default_page_sizeis nil, use
max_page_size`.
143 144 145 146 147 148 149 150 151 |
# File 'lib/graphql/pagination/connection.rb', line 143 def first @first ||= begin capped = limit_pagination_argument(@first_value, max_page_size) if capped.nil? && last.nil? capped = limit_pagination_argument(default_page_size, max_page_size) || max_page_size end capped end end |
#first_value ⇒ Object
Raw access to client-provided values. (max_page_size
not applied to first or last.)
36 37 38 |
# File 'lib/graphql/pagination/connection.rb', line 36 def first_value @first_value end |
#items ⇒ Object (readonly)
Returns A list object, from the application. This is the unpaginated value passed into the connection.
19 20 21 |
# File 'lib/graphql/pagination/connection.rb', line 19 def items @items end |
#last ⇒ Integer?
Returns A clamped last
value. (The underlying instance variable doesn't have limits on it).
164 165 166 |
# File 'lib/graphql/pagination/connection.rb', line 164 def last @last ||= limit_pagination_argument(@last_value, max_page_size) end |
#last_value ⇒ Object
Raw access to client-provided values. (max_page_size
not applied to first or last.)
36 37 38 |
# File 'lib/graphql/pagination/connection.rb', line 36 def last_value @last_value end |
#parent ⇒ Object
Returns the object this collection belongs to.
33 34 35 |
# File 'lib/graphql/pagination/connection.rb', line 33 def parent @parent end |
Instance Method Details
#after ⇒ String?
Returns the client-provided cursor. ""
is treated as nil
.
48 49 50 51 52 53 54 |
# File 'lib/graphql/pagination/connection.rb', line 48 def after if defined?(@after) @after else @after = @after_value == "" ? nil : @after_value end end |
#before ⇒ String?
Returns the client-provided cursor. ""
is treated as nil
.
39 40 41 42 43 44 45 |
# File 'lib/graphql/pagination/connection.rb', line 39 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.
218 219 220 |
# File 'lib/graphql/pagination/connection.rb', line 218 def cursor_for(item) raise PaginationImplementationMissingError, "Implement #{self.class}#cursor_for(item) to return the cursor for #{item.inspect}" end |
#default_page_size ⇒ Object
123 124 125 126 127 128 129 |
# File 'lib/graphql/pagination/connection.rb', line 123 def default_page_size if @has_default_page_size_override @default_page_size else context.schema.default_page_size end end |
#default_page_size=(new_value) ⇒ Object
118 119 120 121 |
# File 'lib/graphql/pagination/connection.rb', line 118 def default_page_size=(new_value) @has_default_page_size_override = true @default_page_size = new_value end |
#edge_nodes ⇒ Object
use #nodes instead
A dynamic alias for compatibility with Relay::BaseConnection.
186 187 188 |
# File 'lib/graphql/pagination/connection.rb', line 186 def edge_nodes nodes end |
#edges ⇒ Array<Edge>
Returns #nodes, but wrapped with Edge instances.
169 170 171 |
# File 'lib/graphql/pagination/connection.rb', line 169 def edges @edges ||= nodes.map { |n| @edge_class.new(n, self) } end |
#end_cursor ⇒ String
Returns The cursor of the last item in #nodes.
211 212 213 |
# File 'lib/graphql/pagination/connection.rb', line 211 def end_cursor nodes.last && cursor_for(nodes.last) end |
#has_default_page_size_override? ⇒ Boolean
131 132 133 |
# File 'lib/graphql/pagination/connection.rb', line 131 def has_default_page_size_override? @has_default_page_size_override end |
#has_max_page_size_override? ⇒ Boolean
114 115 116 |
# File 'lib/graphql/pagination/connection.rb', line 114 def has_max_page_size_override? @has_max_page_size_override end |
#has_next_page ⇒ Boolean
Returns True if there are more items after this page.
196 197 198 |
# File 'lib/graphql/pagination/connection.rb', line 196 def has_next_page raise PaginationImplementationMissingError, "Implement #{self.class}#has_next_page to return the next-page check" end |
#has_previous_page ⇒ Boolean
Returns True if there were items before these items.
201 202 203 |
# File 'lib/graphql/pagination/connection.rb', line 201 def has_previous_page raise PaginationImplementationMissingError, "Implement #{self.class}#has_previous_page to return the previous-page check" end |
#max_page_size ⇒ Object
106 107 108 109 110 111 112 |
# File 'lib/graphql/pagination/connection.rb', line 106 def max_page_size if @has_max_page_size_override @max_page_size else context.schema.default_max_page_size end end |
#max_page_size=(new_value) ⇒ Object
101 102 103 104 |
# File 'lib/graphql/pagination/connection.rb', line 101 def max_page_size=(new_value) @has_max_page_size_override = true @max_page_size = new_value end |
#nodes ⇒ Array<Object>
Returns A slice of #items, constrained by @first_value/@after_value/@last_value/@before_value.
180 181 182 |
# File 'lib/graphql/pagination/connection.rb', line 180 def nodes raise PaginationImplementationMissingError, "Implement #{self.class}#nodes to paginate `@items`" end |
#page_info ⇒ Object
The connection object itself implements PageInfo
fields
191 192 193 |
# File 'lib/graphql/pagination/connection.rb', line 191 def page_info self end |
#range_add_edge(item) ⇒ Edge
This is called by Relay::RangeAdd
-- it can be overridden
when item
needs some modifications based on this connection's state.
158 159 160 |
# File 'lib/graphql/pagination/connection.rb', line 158 def range_add_edge(item) edge_class.new(item, self) end |
#start_cursor ⇒ String
Returns The cursor of the first item in #nodes.
206 207 208 |
# File 'lib/graphql/pagination/connection.rb', line 206 def start_cursor nodes.first && cursor_for(nodes.first) end |
#was_authorized_by_scope_items? ⇒ Boolean
97 98 99 |
# File 'lib/graphql/pagination/connection.rb', line 97 def @was_authorized_by_scope_items end |