Skip to content

How To: Set a Custom Base Connection class to provide totalCount and totalPageCount fields on all Connections

Adam Coffman edited this page Mar 5, 2021 · 4 revisions

Create a custom base connection class for your project:

# frozen_string_literal: true

module Types
  # Base Connection Class
  class BaseConnection < GraphQL::Types::Relay::BaseConnection
    field :total_count, Integer, 'Total # of objects returned from this Plural Query', null: false
    def total_count
      object.items&.count
    end

    field :total_page_count, Integer, 'Total # of pages, based on total count and pagesize', null: false
    def total_page_count
      my_total_count = object.items&.count
      return 1 unless my_total_count&.positive?
      # get total count and create array with total count as first item
      possible_page_sizes = [my_total_count]

      # add first and last argument counts to the array if they exist
      possible_page_sizes << object.first
      possible_page_sizes << object.last

      # get the smallest of the array items
      actual_page_size = possible_page_sizes.compact.min

      # return the total_count divided by the page size, rounded up
      (my_total_count / actual_page_size.to_f).ceil
    end
  end
end

(I'm sure the total_page_count method above could be cleaned up some)

Then just create your specific connection classes based of the one above.

frozen_string_literal: true

module Directory
  module Connections
    # Define Graphql Connection for widgets
    class WidgetsConnection < ::Types::BaseConnection
      graphql_name 'WidgetsConnection'
      edge_type(Directory::Edges::WidgetsEdge)
    end
  end
end

Now in your connection queries you can do call those fields:

{
  widgets(first: 5) {
    totalCount
    totalPageCount
    edges {
      node {
        id
      }
    }
  }
}

... and get a response like this:

{
  "data": {
    "widgets": {
      "totalCount": 179,
      "totalPageCount": 36,
      "edges": [
        {
          "node": {
            "id": "1"
          }
        },
        {
          "node": {
            "id": "2"
          }
        },
        {
          "node": {
            "id": "3"
          }
        },
        {
          "node": {
            "id": "4"
          }
        },
        {
          "node": {
            "id": "5"
          }
        }
      ]
    }
  }
}