Overview
The Rails::GraphQL::Directive class provides a way to define directives that can modify the behavior of schema elements or execution. Directives work as event listeners and triggers.
Namespace: Rails::GraphQL
Extends:
ActiveSupport::Autoload
Helpers::WithEvents
Helpers::WithCallbacks
Helpers::WithArguments
Helpers::WithGlobalID
Helpers::Registerable
Directive Locations
Directives can be placed on various schema elements:
Locations where directives can be used in queries:
:query - On query operations
:mutation - On mutation operations
:subscription - On subscription operations
:field - On field selections
:fragment_definition - On fragment definitions
:fragment_spread - On fragment spreads
:inline_fragment - On inline fragments
Show Definition Locations
Locations where directives can be used in schema definitions:
:schema - On schema definition
:scalar - On scalar types
:object - On object types
:field_definition - On field definitions
:argument_definition - On argument definitions
:interface - On interface types
:union - On union types
:enum - On enum types
:enum_value - On enum values
:input_object - On input object types
:input_field_definition - On input field definitions
Class Attributes
Whether the directive can be used multiple times on the same location
class MyDirective < Rails::GraphQL::Directive
self . repeatable = true
end
Class Methods
kind
Return the kind of object, always :directive.
Returns: Symbol
Directive . kind # => :directive
base_type
Return the base directive class.
Returns: Rails::GraphQL::Directive
MyDirective . base_type # => Rails::GraphQL::Directive
Alias: gid_base_class
gql_name
Get the GraphQL name of the directive (camelCase with lowercase first letter).
Returns: String
DeprecatedDirective . gql_name # => "deprecated"
CachedDirective . gql_name # => "cached"
locations
Get the set of valid locations for this directive.
Returns: Set<Symbol>
Directive . locations # => Set[:field, :fragment_definition, ...]
placed_on
Add valid locations for the directive (merges with inherited locations).
Locations where the directive can be used
class CachedDirective < Rails::GraphQL::Directive
placed_on :field , :field_definition
end
placed_on!
Override valid locations for the directive (replaces inherited locations).
Locations where the directive can be used
class CustomDirective < Rails::GraphQL::Directive
placed_on! :field , :object
end
build
Build a directive instance with parsed arguments.
Arguments as key-value pairs
Returns: Directive instance
directive = DeprecatedDirective . build ( reason: 'Use newField instead' )
find_by_gid
Find and optionally instantiate a directive by its Global ID.
Returns: Directive class or instance
directive = Directive . find_by_gid (gid)
Constructor
initialize
Positional arguments struct
Named arguments as keyword arguments
# Using keyword arguments
directive = DeprecatedDirective . new ( reason: 'Use newField instead' )
# Shortcut using callable class
directive = DeprecatedDirective ( reason: 'Use newField instead' )
Instance Attributes
Arguments provided to the directive instance (frozen)
Current event context (if within event callback)
Instance Methods
assign_owner!
Assign the owner of the directive (can only be called once).
The schema element that owns this directive
Raises: ArgumentError if owner already assigned
directive. assign_owner! (field)
args_as_json
Convert all arguments to their JSON representation.
Returns: Hash
directive. args_as_json # => { "reason" => "Use newField instead" }
args_to_json
Convert all arguments to their JSON string representation.
Returns: Hash
directive. args_to_json # => { "reason" => "\"Use newField instead\"" }
all_events
Get all events with the directive instance as callback context.
Returns: Hash - Event name to callbacks mapping
events = directive. all_events
validate!
Validate the directive instance and its arguments.
Raises: ArgumentError if directive is unbounded or has invalid arguments
Combine directives into an array.
Another directive to combine
Returns: Array<Directive>
Alias: &
combined = DeprecatedDirective ( reason: 'Old' ) + CachedDirective ( ttl: 60 )
# => [#<@deprecated>, #<@cached>]
Delegation
The following methods are delegated to the class:
locations - Get valid locations
gql_name - Get GraphQL name
gid_base_class - Get base class
repeatable? - Check if repeatable
Event Filters
Directives support event filters to control when they trigger:
:for Filter
Trigger directive for specific types.
on :resolve , for: User do
# Only triggered when resolving User type
end
:on Filter
Trigger directive on specific events.
on :resolve , on: Field do
# Only triggered when resolving fields
end
:during Filter
Trigger directive during specific phases.
on :resolve , during: :execution do
# Only triggered during execution phase
end
Built-in Directives
@deprecated
Marks fields or enum values as deprecated.
Explanation for deprecation
field :old_field , :string , directives: DeprecatedDirective ( reason: 'Use newField instead' )
@include
Conditionally include fields in query execution.
query {
user {
name
email @include ( if: $includeEmail )
}
}
@skip
Conditionally skip fields in query execution.
query {
user {
name
email @skip ( if: $skipEmail )
}
}
@specifiedBy
Provides a URL specification for scalar types.
URL to the scalar specification
class UUID < Rails::GraphQL::Type::Scalar
directives SpecifiedByDirective ( url: 'https://tools.ietf.org/html/rfc4122' )
end
@cached
Cache field resolution results.
field :expensive_calculation , :int , directives: CachedDirective ( ttl: 300 )
Example: Custom Directive
class AuthorizeDirective < Rails::GraphQL::Directive
desc 'Checks if the user has required permissions'
# Can be used on fields and field definitions
placed_on :field , :field_definition
# Define arguments
argument :permission , :string , null: false
argument :resource , :string
# Can be used multiple times
self . repeatable = true
# Event callback - triggered before field resolution
on :resolve , during: :prepare do
user = event. request . context . current_user
unless user. has_permission? (args. permission , args. resource )
raise GraphQL :: UnauthorizedError , "Missing permission: #{ args. permission } "
end
end
end
# Usage in schema
class User < Rails::GraphQL::Type::Object
field :email , :string , directives: AuthorizeDirective ( permission: 'read:email' )
field :ssn , :string , directives: [
AuthorizeDirective ( permission: 'read:pii' ),
AuthorizeDirective ( permission: 'read:ssn' )
]
end
Example: Rate Limiting Directive
class RateLimitDirective < Rails::GraphQL::Directive
desc 'Limits the rate of field requests'
placed_on :field_definition
argument :limit , :int , null: false , desc: 'Maximum requests per window'
argument :window , :int , default: 60 , desc: 'Time window in seconds'
on :resolve , during: :prepare do
key = "rate_limit: #{ event. field . gql_name } : #{ event. request . context . user_id } "
count = Rails . cache . increment (key, 1 , expires_in: args. window . seconds )
if count > args. limit
raise GraphQL :: RateLimitError , "Rate limit exceeded for #{ event. field . gql_name } "
end
end
end
# Usage
class Query < Rails::GraphQL::Type::Object
field :search , [ Result ], directives: RateLimitDirective ( limit: 100 , window: 60 ) do
argument :term , :string , null: false
end
end
Example: Logging Directive
class LogDirective < Rails::GraphQL::Directive
desc 'Logs field resolution timing'
placed_on :field , :field_definition
argument :level , :string , default: 'info'
on :resolve , during: :before do
event[ :start_time ] = Time . current
end
on :resolve , during: :after do
duration = Time . current - event[ :start_time ]
Rails . logger . public_send (
args. level ,
"Field #{ event. field . gql_name } resolved in #{ duration } s"
)
end
end
# Usage
field :expensive_query , :Result , directives: LogDirective ( level: 'debug' )