class GraphQL::Relay::BaseConnection

Subclasses must implement:

- {#cursor_from_node}, which returns an opaque cursor for the given item
- {#sliced_nodes}, which slices by `before` & `after`
- {#paged_nodes}, which applies `first` & `last` limits

In a subclass, you have access to

- {#nodes}, the collection which the connection will wrap
- {#first}, {#after}, {#last}, {#before} (arguments passed to the field)
- {#max_page_size} (the specified maximum page size that can be returned from a connection)

Constants

CONNECTION_IMPLEMENTATIONS

Map of collection class names -> connection_classes eg `{“Array” => ArrayConnection}`

CURSOR_SEPARATOR

Just to encode data in the cursor, use something that won't conflict

Attributes

arguments[R]
context[R]
field[R]
max_page_size[R]
nodes[R]
parent[R]

Public Class Methods

connection_for_nodes(nodes) click to toggle source

Find a connection implementation suitable for exposing `nodes`

@param nodes [Object] A collection of nodes (eg, Array, AR::Relation) @return [subclass of BaseConnection] a connection Class for wrapping `nodes`

# File lib/graphql/relay/base_connection.rb, line 26
def connection_for_nodes(nodes)
  # Check for class _names_ because classes can be redefined in Rails development
  nodes.class.ancestors.each do |ancestor|
    conn_impl = CONNECTION_IMPLEMENTATIONS[ancestor.name]
    if conn_impl
      return conn_impl
    end
  end
  # Should have found a connection during the loop:
  raise("No connection implementation to wrap #{nodes.class} (#{nodes})")
end
new(nodes, arguments, field: nil, max_page_size: nil, parent: nil, context: nil) click to toggle source

Make a connection, wrapping `nodes` @param nodes [Object] The collection of nodes @param arguments [GraphQL::Query::Arguments] Query arguments @param field [GraphQL::Field] The underlying field @param #max_page_size [Int] The maximum number of results to return @param parent [Object] The object which this collection belongs to @param context [GraphQL::Query::Context] The context from the field being resolved

# File lib/graphql/relay/base_connection.rb, line 56
def initialize(nodes, arguments, field: nil, max_page_size: nil, parent: nil, context: nil)
  @context = context
  @nodes = nodes
  @arguments = arguments
  @field = field
  @parent = parent
  @encoder = context ? @context.schema.cursor_encoder : GraphQL::Schema::Base64Encoder
  @max_page_size = max_page_size.nil? && context ? @context.schema.default_max_page_size : max_page_size
end
register_connection_implementation(nodes_class, connection_class) click to toggle source

Add `connection_class` as the connection wrapper for `nodes_class` eg, `RelationConnection` is the implementation for `AR::Relation` @param nodes_class [Class] A class representing a collection (eg, Array, AR::Relation) @param connection_class [Class] A class implementing Connection methods

# File lib/graphql/relay/base_connection.rb, line 42
def register_connection_implementation(nodes_class, connection_class)
  CONNECTION_IMPLEMENTATIONS[nodes_class.name] = connection_class
end

Public Instance Methods

after() click to toggle source

The value passed as `after:`, if there was one @return [String, nil]

# File lib/graphql/relay/base_connection.rb, line 82
def after
  arguments[:after]
end
before() click to toggle source

The value passed as `before:`, if there was one @return [String, nil]

# File lib/graphql/relay/base_connection.rb, line 94
def before
  arguments[:before]
end
cursor_from_node(object) click to toggle source

An opaque operation which returns a connection-specific cursor.

# File lib/graphql/relay/base_connection.rb, line 138
def cursor_from_node(object)
  raise NotImplementedError, "must return a cursor for this object/connection pair"
end
decode(data) click to toggle source
# File lib/graphql/relay/base_connection.rb, line 70
def decode(data)
  @encoder.decode(data, nonce: true)
end
edge_nodes() click to toggle source

These are the nodes to render for this connection, probably wrapped by {GraphQL::Relay::Edge}

# File lib/graphql/relay/base_connection.rb, line 100
def edge_nodes
  @edge_nodes ||= paged_nodes
end
encode(data) click to toggle source
# File lib/graphql/relay/base_connection.rb, line 66
def encode(data)
  @encoder.encode(data, nonce: true)
end
end_cursor() click to toggle source

Used by `pageInfo`

# File lib/graphql/relay/base_connection.rb, line 129
def end_cursor
  if end_node = (respond_to?(:paged_nodes_array, true) ? paged_nodes_array : paged_nodes).last
    return cursor_from_node(end_node)
  else
    return nil
  end
end
first() click to toggle source

The value passed as `first:`, if there was one. Negative numbers become `0`. @return [Integer, nil]

# File lib/graphql/relay/base_connection.rb, line 76
def first
  @first ||= get_limited_arg(:first)
end
has_next_page() click to toggle source

Used by `pageInfo`

# File lib/graphql/relay/base_connection.rb, line 110
def has_next_page
  !!(first && sliced_nodes.count > first)
end
has_previous_page() click to toggle source

Used by `pageInfo`

# File lib/graphql/relay/base_connection.rb, line 115
def has_previous_page
  !!(last && sliced_nodes.count > last)
end
inspect() click to toggle source
# File lib/graphql/relay/base_connection.rb, line 142
def inspect
  "#<GraphQL::Relay::Connection @parent=#{@parent.inspect} @arguments=#{@arguments.to_h.inspect}>"
end
last() click to toggle source

The value passed as `last:`, if there was one. Negative numbers become `0`. @return [Integer, nil]

# File lib/graphql/relay/base_connection.rb, line 88
def last
  @last ||= get_limited_arg(:last)
end
page_info() click to toggle source

Support the `pageInfo` field

# File lib/graphql/relay/base_connection.rb, line 105
def page_info
  self
end
start_cursor() click to toggle source

Used by `pageInfo`

# File lib/graphql/relay/base_connection.rb, line 120
def start_cursor
  if start_node = (respond_to?(:paged_nodes_array, true) ? paged_nodes_array : paged_nodes).first
    return cursor_from_node(start_node)
  else
    return nil
  end
end

Private Instance Methods

get_limited_arg(arg_name) click to toggle source

Return a sanitized `arguments` (don't allow negatives)

# File lib/graphql/relay/base_connection.rb, line 149
def get_limited_arg(arg_name)
  arg_value = arguments[arg_name]
  if arg_value.nil?
    arg_value
  elsif arg_value < 0
    0
  else
    arg_value
  end
end
paged_nodes() click to toggle source
# File lib/graphql/relay/base_connection.rb, line 160
def paged_nodes
  raise NotImplementedError, "must return nodes for this connection after paging"
end
sliced_nodes() click to toggle source
# File lib/graphql/relay/base_connection.rb, line 164
def sliced_nodes
  raise NotImplementedError, "must return  all nodes for this connection after chopping off first and last"
end