⚠ New Class-Based API ⚠

This describes a new API in v1.8.0. Check the upgrade notes for more info.

Definition

A GraphQL system is called a schema. The schema contains all the types and fields in the system. The schema executes queries and publishes an introspection system.

Your GraphQL schema is a class that extends GraphQL::Schema, for example:

class MyAppSchema < GraphQL::Schema
  max_complexity 400
  query Types::Query
  use GraphQL::Batch

  # Define hooks as class methods:
  def self.resolve_type(type, obj, ctx)
    # ...
  end

  def self.object_from_id(node_id, ctx)
    # ...
  end

  def self.id_from_object(object, type, ctx)
    # ...
  end
end

There are lots of schema configuration options:

Root Objects, Introspection and Orphan Types

A GraphQL schema is a web of interconnected types, and it has a few starting points for discovering the elements of that web:

Root types (query, mutation, and subscription) are the entry points for queries to the system. Each one is an object type which can be connected to the schema by a method with the same name:

class MySchema < GraphQL::Schema
  # Required:
  query Types::Query
  # Optional:
  mutation Types::Mutation
  subscription Types::Subscription
end

Introspection is a built-in part of the schema. Every schema has a default introspection system, but you can customize it and hook it up with introspection:

class MySchema < GraphQL::Schema
  introspection CustomIntrospection
end

Orphan Types are types which should be in the schema, but can’t be discovered by traversing the types and fields from query, mutation or subscription. This has one very specific use case, see Orphan Types.

class MySchema < GraphQL::Schema
  orphan_types [Types::Comment, ...]
end

Object Identification Hooks

A GraphQL schema needs a handful of hooks for finding and disambiguating objects while queries are executed.

resolve_type is used when a specific object’s corresponding GraphQL type must be determined. This happens for fields that return interface or union types. The class method def self.resolve_type is used:

class MySchema < GraphQL::Schema
  def self.resolve_type(abstract_type, object, context)
    # Disambiguate `object`, from among `abstract_type`'s members
    # (`abstract_type` is an interface or union type.)
  end
end

object_from_id is used by Relay’s node(id: ID!): Node field. It receives a unique ID and must return the object for that ID, or nil if the object isn’t found (or if the should be hidden from the current user).

class MySchema < GraphQL::Schema
  def self.object_from_id(unique_id, context)
    # Find and return the object for `unique_id`
    # or `nil`
  end
end

id_from_object is used to implement Relay’s Node.id field. It should return a unique ID for the given object. This ID will later be sent to object_from_id to refetch the object.

class MySchema < GraphQL::Schema
  def self.id_from_object(object, type, context)
    # Return a unique ID for `object`, whose GraphQL type is `type`
  end
end

Execution Configuration

instrument attaches instrumenters to the schema, see Instrumentation for more information.

class MySchema < GraphQL::Schema
  instrument :field, ResolveTimerInstrumentation
end

tracer is another way to hook into execution, see Tracing for more.

class MySchema < GraphQL::Schema
  tracer MetricTracer
end

query_analyzer and multiplex_analyzer accept processors for ahead-of-type query analysis, see Analysis for more.

class MySchema < GraphQL::Schema
  query_analyzer MyQueryAnalyzer.new
end

lazy_resolve registers classes with lazy execution:

class MySchema < GraphQL::Schema
  lazy_resolve Promise, :sync
end

type_error handles type errors at runtime, read more in the Type Errors guide.

class MySchema < GraphQL::Schema
  def self.type_error(type_err, context)
    # Handle `type_err` in some way
  end
end

rescue_from accepts error handlers for application errors, for example:

class MySchema < GraphQL::Schema
  rescue_from(ActiveRecord::RecordNotFound) { "Not found" }
end

Context Class

Usually, context is an instance of GraphQL::Query::Context, but you can create a custom subclass and attach it with .context_class, for example:

class CustomContext < GraphQL::Query::Context
  # Shorthand to get the current user
  def viewer
    self[:viewer]
  end
end

class MySchema < GraphQL::Schema
  context_class CustomContext
end

Then, during execution, context will be an instance CustomContext.

Default Limits

max_depth and max_complexity apply some limits to incoming queries. See Complexity and Depth for more.

default_max_page_size applies limits to Connection fields.

class MySchema < GraphQL::Schema
  max_depth 10
  max_complexity 300
  default_max_page_size 20
end

Plugins

A plugin is an object that responds to #use. Plugins are used to attach new behavior to a schema without a lot of API overhead. For example, the gem’s monitoring tools are plugins:

class MySchema < GraphQL::Schema
  use(GraphQL::Tracing::NewRelicTracing)
end