Module: ActiveProject::Connections::Pagination

Includes:
HttpClient
Included in:
GraphQl, Rest
Defined in:
lib/active_project/connections/pagination.rb

Overview

Relay + Link-header pagination helpers usable for REST and GraphQL

Constant Summary

Constants included from HttpClient

HttpClient::DEFAULT_HEADERS, HttpClient::DEFAULT_RETRY_OPTS

Instance Attribute Summary

Attributes included from HttpClient

#connection, #last_response

Instance Method Summary collapse

Methods included from HttpClient

#build_connection, #request

Methods included from Base

#parse_link_header

Instance Method Details

#each_edge(query:, connection_path:, variables: {}, after_key: "after") {|node| ... } ⇒ Object

Relay-style paginator (pageInfo{ hasNextPage, endCursor })

Parameters:

  • connection_path (Array<String>)

    path inside JSON to the connection node

Yield Parameters:

  • node (Object)

    each edge.node yielded



30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/active_project/connections/pagination.rb', line 30

def each_edge(query:, connection_path:, variables: {}, after_key: "after")
  cursor = nil
  loop do
    vars = variables.merge(after_key => cursor)
    data = yield(vars) # caller executes GraphQL request, returns data hash
    conn = data.dig(*connection_path)
    conn["edges"].each { |edge| yield edge["node"] }
    break unless conn["pageInfo"]["hasNextPage"]

    cursor = conn["pageInfo"]["endCursor"]
  end
end

#each_page(path, method: :get, body: nil, query: {}, headers: {}) {|page| ... } ⇒ Object

Generic RFC-5988 “Link” header paginator (GitHub/Jira/Trello style)

Yield Parameters:

  • page (Object)

    parsed JSON for each HTTP page



11
12
13
14
15
16
17
18
19
20
21
22
23
24
# File 'lib/active_project/connections/pagination.rb', line 11

def each_page(path, method: :get, body: nil, query: {}, headers: {})
  next_url = path
  loop do
    page = request(method, next_url, body: body, query: query, headers: headers)
    yield page
    link_header = @last_response&.headers&.[]("Link")
    next_url = parse_link_header(link_header)["next"]
    break unless next_url

    # After first request we follow absolute URLs; zero out body/query for GETs
    body = nil if method == :get
    query = {}
  end
end