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