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.
68 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 96 97 98 99 100 |
# File 'lib/graphql/pagination/connection.rb', line 68 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 = if @context current_runtime_state = Thread.current[:__graphql_runtime_info] query_runtime_state = current_runtime_state[@context.query] query_runtime_state. else nil end end |
Instance Attribute Details
#after_value ⇒ Object
Raw access to client-provided values. (max_page_size
not applied to first or last.)
35 36 37 |
# File 'lib/graphql/pagination/connection.rb', line 35 def after_value @after_value end |
#arguments ⇒ Hash<Symbol => Object>
Returns The field arguments from the field that returned this connection.
56 57 58 |
# File 'lib/graphql/pagination/connection.rb', line 56 def arguments @arguments end |
#before_value ⇒ Object
Raw access to client-provided values. (max_page_size
not applied to first or last.)
35 36 37 |
# File 'lib/graphql/pagination/connection.rb', line 35 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.
179 180 181 |
# File 'lib/graphql/pagination/connection.rb', line 179 def edge_class @edge_class end |
#field ⇒ GraphQL::Schema::Field
Returns The field this connection was returned by.
182 183 184 |
# File 'lib/graphql/pagination/connection.rb', line 182 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_size is nil, use
max_page_size`.
148 149 150 151 152 153 154 155 156 |
# File 'lib/graphql/pagination/connection.rb', line 148 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.)
35 36 37 |
# File 'lib/graphql/pagination/connection.rb', line 35 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).
169 170 171 |
# File 'lib/graphql/pagination/connection.rb', line 169 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.)
35 36 37 |
# File 'lib/graphql/pagination/connection.rb', line 35 def last_value @last_value end |
#parent ⇒ Object
Returns the object this collection belongs to.
32 33 34 |
# File 'lib/graphql/pagination/connection.rb', line 32 def parent @parent end |
Instance Method Details
#after ⇒ String?
Returns the client-provided cursor. ""
is treated as nil
.
47 48 49 50 51 52 53 |
# File 'lib/graphql/pagination/connection.rb', line 47 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
.
38 39 40 41 42 43 44 |
# File 'lib/graphql/pagination/connection.rb', line 38 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.
223 224 225 |
# File 'lib/graphql/pagination/connection.rb', line 223 def cursor_for(item) raise PaginationImplementationMissingError, "Implement #{self.class}#cursor_for(item) to return the cursor for #{item.inspect}" end |
#default_page_size ⇒ Object
128 129 130 131 132 133 134 |
# File 'lib/graphql/pagination/connection.rb', line 128 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
123 124 125 126 |
# File 'lib/graphql/pagination/connection.rb', line 123 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.
191 192 193 |
# File 'lib/graphql/pagination/connection.rb', line 191 def edge_nodes nodes end |
#edges ⇒ Array<Edge>
Returns #nodes, but wrapped with Edge instances.
174 175 176 |
# File 'lib/graphql/pagination/connection.rb', line 174 def edges @edges ||= nodes.map { |n| @edge_class.new(n, self) } end |
#end_cursor ⇒ String
Returns The cursor of the last item in #nodes.
216 217 218 |
# File 'lib/graphql/pagination/connection.rb', line 216 def end_cursor nodes.last && cursor_for(nodes.last) end |
#has_default_page_size_override? ⇒ Boolean
136 137 138 |
# File 'lib/graphql/pagination/connection.rb', line 136 def has_default_page_size_override? @has_default_page_size_override end |
#has_max_page_size_override? ⇒ Boolean
119 120 121 |
# File 'lib/graphql/pagination/connection.rb', line 119 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.
201 202 203 |
# File 'lib/graphql/pagination/connection.rb', line 201 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.
206 207 208 |
# File 'lib/graphql/pagination/connection.rb', line 206 def has_previous_page raise PaginationImplementationMissingError, "Implement #{self.class}#has_previous_page to return the previous-page check" end |
#max_page_size ⇒ Object
111 112 113 114 115 116 117 |
# File 'lib/graphql/pagination/connection.rb', line 111 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
106 107 108 109 |
# File 'lib/graphql/pagination/connection.rb', line 106 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.
185 186 187 |
# File 'lib/graphql/pagination/connection.rb', line 185 def nodes raise PaginationImplementationMissingError, "Implement #{self.class}#nodes to paginate `@items`" end |
#page_info ⇒ Object
The connection object itself implements PageInfo
fields
196 197 198 |
# File 'lib/graphql/pagination/connection.rb', line 196 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.
163 164 165 |
# File 'lib/graphql/pagination/connection.rb', line 163 def range_add_edge(item) edge_class.new(item, self) end |
#start_cursor ⇒ String
Returns The cursor of the first item in #nodes.
211 212 213 |
# File 'lib/graphql/pagination/connection.rb', line 211 def start_cursor nodes.first && cursor_for(nodes.first) end |
#was_authorized_by_scope_items? ⇒ Boolean
102 103 104 |
# File 'lib/graphql/pagination/connection.rb', line 102 def @was_authorized_by_scope_items end |