1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
|
---
layout: guide
doc_stub: false
search: true
section: Type Definitions
title: Directives
desc: Special instructions for the GraphQL runtime
index: 10
---
Directives are system-defined keywords with two kinds of uses:
- [runtime directives](#runtime-directives) _modify execution_, so that when they are present, the GraphQL runtime does something different;
- [schema directives](#schema-directives) _annotate schema definitions_, indicating different configurations or metadata about schemas and types.
## 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:
```ruby
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:
- `@skip(if: ...)` skips the selection if the `if: ...` value is truthy ({{ "GraphQL::Schema::Directive::Skip" | api_doc }})
- `@include(if: ...)` includes the selection if the `if: ...` value is truthy ({{ "GraphQL::Schema::Directive::Include" | api_doc }})
### Custom Runtime Directives
Custom directives extend {{ "GraphQL::Schema::Directive" | api_doc }}:
```ruby
# 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(...)`:
```ruby
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(...)`:
```ruby
query {
field @myDirective {
id
}
}
```
{{ "GraphQL::Schema::Directive::Feature" | api_doc }} and {{ "GraphQL::Schema::Directive::Transform" | api_doc }} are included in the library as examples.
### Runtime hooks
Directive classes may implement the following class methods to interact with the runtime:
- `def self.include?(obj, args, ctx)`: If this hook returns `false`, the nodes flagged by this directive will be skipped at runtime.
- `def self.resolve(obj, args, ctx)`: Wraps the resolution of flagged nodes. Resolution is passed as a __block__, so `yield` will continue resolution.
Looking for a runtime hook that isn't listed here? {% open_an_issue "New directive hook: @something", "<!-- Describe how the directive would be used and then how you might implement it --> " %} 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:
```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" | api_doc }}:
```ruby
# 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(...)`:
```ruby
class Types::JobPosting < Types::BaseObject
directive Directives::Permission, level: "manager"
end
```
Arguments and fields also accept a `directives:` keyword:
```ruby
field :salary, Integer, null: false,
directives: { Directives::Permission => { level: "manager" } }
```
After that:
- the configured object's `.directives` method will return an array containing an instance of the specified directive
- IDL dumps (from {{ "Schema.to_definition" | api_doc }}) will include the configured directives
Similarly, {{ "Schema.from_definition" | api_doc }} parses directives from IDL strings.
For a couple of built-in examples, check out:
- {{ "GraphQL::Schema::Directive::Deprecated" | api_doc }} which implements `deprecation_reason` (via {{ "GraphQL::Schema::Member::HasDeprecationReason" | api_doc}})
- {{ "GraphQL::Schema::Directive::Flagged" | api_doc }}, which is an example of using schema directives to implement {% internal_link "visibility", "/authorization/visibility" %}
## Custom Name
By default, the directive's name is taken from the class name. You can override this with `graphql_name`, for example:
```ruby
class Directives::IsPrivate < GraphQL::Schema::Directive
graphql_name "someOtherName"
end
```
## Arguments
Like fields, directives may have {% internal_link "arguments", "/fields/arguments" %} :
```ruby
argument :if, Boolean,
description: "Skips the selection if this condition is true"
```
|