Class: GraphQL::Relay::BaseConnection

Inherits:
Object
  • Object
show all
Defined in:
lib/graphql/relay/base_connection.rb

Overview

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

- {#object}, the object 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)

Direct Known Subclasses

ArrayConnection, RelationConnection

Constant Summary collapse

CURSOR_SEPARATOR =

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

"---"
CONNECTION_IMPLEMENTATIONS =

Map of collection class names -> connection_classes eg => ArrayConnection

{}
METHODS_FROM_ARGUMENTS =

Provide easy access to provided arguments:

[:first, :after, :last, :before, :order]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(object, arguments, max_page_size: nil, parent: nil) ⇒ BaseConnection

Make a connection, wrapping ‘object`

Parameters:

  • The

    collection of results

  • Query

    arguments

  • max_page_size (Int) (defaults to: nil)

    The maximum number of results to return

  • parent (Object) (defaults to: nil)

    The object which this collection belongs to



57
58
59
60
61
62
# File 'lib/graphql/relay/base_connection.rb', line 57

def initialize(object, arguments, max_page_size: nil, parent: nil)
  @object = object
  @arguments = arguments
  @max_page_size = max_page_size
  @parent = parent
end

Instance Attribute Details

#argumentsObject (readonly)

Returns the value of attribute arguments.



50
51
52
# File 'lib/graphql/relay/base_connection.rb', line 50

def arguments
  @arguments
end

#max_page_sizeObject (readonly)

Returns the value of attribute max_page_size.



50
51
52
# File 'lib/graphql/relay/base_connection.rb', line 50

def max_page_size
  @max_page_size
end

#objectObject (readonly)

Returns the value of attribute object.



50
51
52
# File 'lib/graphql/relay/base_connection.rb', line 50

def object
  @object
end

#parentObject (readonly)

Returns the value of attribute parent.



50
51
52
# File 'lib/graphql/relay/base_connection.rb', line 50

def parent
  @parent
end

Class Method Details

.connection_for_items(items) ⇒ subclass of BaseConnection

Find a connection implementation suitable for exposing ‘items`

Parameters:

  • A (Object)

    collection of items (eg, Array, AR::Relation)

Returns:

  • (subclass of BaseConnection)

    a connection Class for wrapping ‘items`



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/graphql/relay/base_connection.rb', line 25

def self.connection_for_items(items)
  # We check class membership by comparing class names rather than
  # identity to prevent this from being broken by Rails autoloading.
  # Changes to the source file for ItemsClass in Rails apps cause it to be
  # reloaded as a new object, so if we were to use `is_a?` here, it would
  # no longer match any registered custom connection types.
  ancestor_names = items.class.ancestors.map(&:name)
  implementation = CONNECTION_IMPLEMENTATIONS.find do |items_class_name, connection_class|
    ancestor_names.include? items_class_name
  end
  if implementation.nil?
    raise("No connection implementation to wrap #{items.class} (#{items})")
  else
    implementation[1]
  end
end

.register_connection_implementation(items_class, connection_class) ⇒ Object

Add ‘connection_class` as the connection wrapper for `items_class` eg, `RelationConnection` is the implementation for `AR::Relation`

Parameters:

  • A (Class)

    class representing a collection (eg, Array, AR::Relation)

  • A (Class)

    class implementing Connection methods



46
47
48
# File 'lib/graphql/relay/base_connection.rb', line 46

def self.register_connection_implementation(items_class, connection_class)
  CONNECTION_IMPLEMENTATIONS[items_class.name] = connection_class
end

Instance Method Details

#afterObject

The value passed as ‘after:`, if there was one



77
78
79
80
81
# File 'lib/graphql/relay/base_connection.rb', line 77

METHODS_FROM_ARGUMENTS.each do |arg_name|
  define_method(arg_name) do
    arguments[arg_name]
  end
end

#beforeObject

The value passed as ‘before:`, if there was one



77
78
79
80
81
# File 'lib/graphql/relay/base_connection.rb', line 77

METHODS_FROM_ARGUMENTS.each do |arg_name|
  define_method(arg_name) do
    arguments[arg_name]
  end
end

#cursor_from_node(object) ⇒ Object

An opaque operation which returns a connection-specific cursor.

Raises:

  • (NotImplementedError)


123
124
125
# File 'lib/graphql/relay/base_connection.rb', line 123

def cursor_from_node(object)
  raise NotImplementedError, "must return a cursor for this object/connection pair"
end

#edge_nodesObject

These are the items to render for this connection, probably wrapped by Edge



85
86
87
# File 'lib/graphql/relay/base_connection.rb', line 85

def edge_nodes
  @edge_nodes ||= paged_nodes
end

#end_cursorObject

Used by ‘pageInfo`



114
115
116
117
118
119
120
# File 'lib/graphql/relay/base_connection.rb', line 114

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

#firstObject

The value passed as ‘first:`, if there was one



77
78
79
80
81
# File 'lib/graphql/relay/base_connection.rb', line 77

METHODS_FROM_ARGUMENTS.each do |arg_name|
  define_method(arg_name) do
    arguments[arg_name]
  end
end

#has_next_pageObject

Used by ‘pageInfo`



95
96
97
# File 'lib/graphql/relay/base_connection.rb', line 95

def has_next_page
  !!(first && sliced_nodes.count > first)
end

#has_previous_pageObject

Used by ‘pageInfo`



100
101
102
# File 'lib/graphql/relay/base_connection.rb', line 100

def has_previous_page
  !!(last && sliced_nodes.count > last)
end

#lastObject

The value passed as ‘last:`, if there was one



77
78
79
80
81
# File 'lib/graphql/relay/base_connection.rb', line 77

METHODS_FROM_ARGUMENTS.each do |arg_name|
  define_method(arg_name) do
    arguments[arg_name]
  end
end

#orderObject

The value passed as ‘order:`, if there was one



77
78
79
80
81
# File 'lib/graphql/relay/base_connection.rb', line 77

METHODS_FROM_ARGUMENTS.each do |arg_name|
  define_method(arg_name) do
    arguments[arg_name]
  end
end

#page_infoObject

Support the ‘pageInfo` field



90
91
92
# File 'lib/graphql/relay/base_connection.rb', line 90

def page_info
  self
end

#start_cursorObject

Used by ‘pageInfo`



105
106
107
108
109
110
111
# File 'lib/graphql/relay/base_connection.rb', line 105

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