Class: GraphQL::Connections::Stable

Inherits:
Pagination::Connection
  • Object
show all
Defined in:
lib/graphql/connections/stable.rb

Overview

Cursor-based pagination to work with ‘ActiveRecord::Relation`s. Implements a mechanism for serving stable connections based on column values. If objects are created or destroyed during pagination, the list of items won’t be disrupted.

Inspired by ‘GraphQL::Pro`s Stable Relation Connections graphql-ruby.org/pagination/stable_relation_connections.html

For more information see GraphQL Cursor Connections Specification relay.dev/graphql/connections.htm

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args, primary_key: nil, opaque_cursor: true, **kwargs) ⇒ Stable



19
20
21
22
23
24
# File 'lib/graphql/connections/stable.rb', line 19

def initialize(*args, primary_key: nil, opaque_cursor: true, **kwargs)
  @primary_key = primary_key
  @opaque_cursor = opaque_cursor

  super(*args, **kwargs)
end

Instance Attribute Details

#opaque_cursorObject (readonly)

Returns the value of attribute opaque_cursor.



15
16
17
# File 'lib/graphql/connections/stable.rb', line 15

def opaque_cursor
  @opaque_cursor
end

Instance Method Details

#cursor_for(item) ⇒ Object



54
55
56
57
58
# File 'lib/graphql/connections/stable.rb', line 54

def cursor_for(item)
  cursor = serialize(item[primary_key])
  cursor = encode(cursor) if opaque_cursor
  cursor
end

#has_next_pageObject

rubocop:disable Naming/PredicateName



44
45
46
47
48
49
50
51
52
# File 'lib/graphql/connections/stable.rb', line 44

def has_next_page # rubocop:disable Naming/PredicateName
  if first
    nodes.any? && items.where(arel_table[primary_key].gt(nodes.last[primary_key])).exists?
  elsif before
    items.where(arel_table[primary_key].gteq(before_cursor)).exists?
  else
    false
  end
end

#has_previous_pageObject

rubocop:disable Naming/PredicateName



34
35
36
37
38
39
40
41
42
# File 'lib/graphql/connections/stable.rb', line 34

def has_previous_page # rubocop:disable Naming/PredicateName
  if last
    nodes.any? && items.where(arel_table[primary_key].lt(nodes.first[primary_key])).exists?
  elsif after
    items.where(arel_table[primary_key].lteq(after_cursor)).exists?
  else
    false
  end
end

#nodesObject



30
31
32
# File 'lib/graphql/connections/stable.rb', line 30

def nodes
  @nodes ||= limited_relation
end

#primary_keyObject



26
27
28
# File 'lib/graphql/connections/stable.rb', line 26

def primary_key
  @primary_key ||= items.model.primary_key
end