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:
For defining GraphQL types, see the guides for those types: object types,%20%5Binterface%20types%5D(/type_definitions/interfaces),%20%5Bunion%20types%5D(/type_definitions/unions),%20%20%5Binput%20object%20types%5D(/type_definitions/input_objects),%20%5Benum%20types%5D(/type_definitions/enums),%20and%20%20%5Bscalar%20types%5D(/type_definitions/scalars).
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
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%20or%20%20%5Bunion%5D(/type_definitions/unions) 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 it 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
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 Invariants 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
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.
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
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