Directives

Directives are system-defined keywords with two kinds of uses:

Runtime Directives

Runtime directives are server-defined keywords that modify GraphQL execution. All GraphQL systems have at least two directives, @skip and @include. For example:

query ProfileView($renderingDetailedProfile: Boolean!){
  viewer {
    handle
    # These fields will be included only if the check passes:
    ... @include(if: $renderingDetailedProfile) {
      location
      homepageUrl
    }
  }
}

Here’s how the two built-in directives work:

Custom directives extend GraphQL::Schema::Directive:

# app/graphql/directives/my_directive.rb
class Directives::MyDirective < GraphQL::Schema::Directive
  description "A nice runtime customization"
  location FIELD
end

Then, they’re hooked up to the schema using directive(...):

class MySchema < GraphQL::Schema
  # Attach the custom directive to the schema
  directive(Directives::MyDirective)
end

And you can reference them in the query with @myDirective(...):

query {
  field @myDirective {
    id
  }
}

GraphQL::Schema::Directive::Feature and GraphQL::Schema::Directive::Transform are included in the library as examples.

Runtime hooks

Directive classes may implement the following class methods to interact with the runtime:

Looking for a runtime hook that isn’t listed here? open an issue to start the conversation!

Schema Directives

Schema directives are used in GraphQL’s interface definition language (IDL). For example, @deprecated is built in to GraphQL-Ruby:

type User {
  firstName @deprecated(reason: "Use `name` instead")
  lastName @deprecated(reason: "Use `name` instead")
  name
}

In the schema definition, directives express metadata about types, fields, and arguments.

Custom Schema Directives

To make a custom schema directive, extend GraphQL::Schema::Directive:

# app/graphql/directives/permission.rb
class Directives::Permission < GraphQL::Schema::Directive
  argument :level, String
  locations FIELD_DEFINITION, OBJECT
end

Then, attach it to parts of your schema with directive(...):

class Types::JobPosting < Types::BaseObject
  directive Directives::Permission, level: "manager"
end

Arguments and fields also accept a directives: keyword:

field :salary, Integer, null: false,
  directives: { Directives::Permission => { level: "manager" } }

After that:

Similarly, Schema.from_definition parses directives from IDL strings.

For a couple of built-in examples, check out:

Custom Name

By default, the directive’s name is taken from the class name. You can override this with graphql_name, for example:

class Directives::IsPrivate < GraphQL::Schema::Directive
  graphql_name "someOtherName"
end

Arguments

Like fields, directives may have arguments :

argument :if, Boolean,
  description: "Skips the selection if this condition is true"