Enums are leaf types that represent a fixed set of possible values. They work like string scalars but only accept predefined values, making them perfect for categories, statuses, and other constrained choices.
Basic Enum Definition
Define enums in files or inline within your schema:
File-based Definition
Schema Definition
# app/graphql/enums/role.rb
module GraphQL
class Role < GraphQL::Enum
add 'ADMIN'
add 'SUPPORT'
add 'USER'
end
end
The resulting GraphQL type:
enum Role {
ADMIN
SUPPORT
USER
}
Values are automatically converted to uppercase strings, so :admin, 'admin', and 'ADMIN' all create the same ADMIN value.
Adding Values
Use the add method to define enum values:
enum 'Role' do
# All equivalent - values are uppercased
add :admin
add 'support'
add 'USER'
end
Value Descriptions
Document individual values:
enum 'Episode' do
desc 'One of the films in the Star Wars Trilogy'
add 'NEW_HOPE' , desc: 'Released in 1977.'
add 'EMPIRE' , desc: 'Released in 1980.'
add 'JEDI' , desc: 'Released in 1983.'
end
Deprecating Values
Mark values as deprecated:
enum 'Role' do
add 'ADMIN'
add 'SUPPORT' , deprecated: 'Use ADMIN instead'
add 'LEGACY_USER' , deprecated: true
end
Value Directives
Attach custom directives to values:
enum 'Status' do
add 'ACTIVE'
add 'ARCHIVED' , directives: GraphQL :: DeprecatedDirective . new
end
Index-based Enums
For numeric-based enums in your application, use indexed! to enable automatic conversion:
enum 'Priority' do
add 'LOW'
add 'MEDIUM'
add 'HIGH'
indexed!
end
Before indexed!
After indexed!
GraphQL :: Priority . as_json ( 0 ) # => "0"
GraphQL :: Priority . valid_output? ( 0 ) # => false
Indexed enums only affect output. Input must always use uppercase string values, even for indexed enums.
Using Enums
Enums work as both input and output types:
As Output Fields
object 'User' do
field :id
field :name
field :role , 'Role'
end
mutation_fields do
field :create_user , 'User' , null: false do
argument :name , :string , null: false
argument :role , 'Role' , null: false
end
end
In Queries
mutation {
createUser ( name : "John Doe" , role : ADMIN ) {
id
name
role
}
}
{
"data" : {
"createUser" : {
"id" : "1" ,
"name" : "John Doe" ,
"role" : "ADMIN"
}
}
}
Enum Instances
When received as input, enums are instances with helpful methods:
def create_user ( name: , role: )
# role is a GraphQL::Role instance
role. to_s # => "ADMIN"
role. to_sym # => :admin
role. to_i # => 0 (index position)
role. deprecated? # => false
role. deprecated_reason # => nil
role. description # => "Has superpowers" (if set)
end
Instance Methods
Returns the plain string value: "ADMIN"
Returns a lowercase symbol: :admin
Returns the index position (0-based): 0
Checks if the value is valid for this enum
Returns true if the value has a deprecated directive
Returns the deprecation reason if deprecated
Returns the value’s description if set
Common Patterns
Query Filters
enum 'Episode' , values: %i[new_hope empire jedi]
query_fields do
field :hero , 'Character' do
argument :episode , 'Episode' ,
desc: 'Return for a specific episode'
end
end
def hero ( episode: )
episode. to_i === 1 ? luke_skywalker : r2d2
end
Status Fields
enum 'OrderStatus' do
add 'PENDING'
add 'PROCESSING'
add 'SHIPPED'
add 'DELIVERED'
add 'CANCELLED'
end
object 'Order' do
field :id
field :status , 'OrderStatus'
end
Sort Directions
enum 'SortOrder' , values: %i[asc desc]
query_fields do
field :users , 'User' , array: true do
argument :sort_by , :string
argument :order , 'SortOrder' , default: 'ASC'
end
end
Feature Flags
enum 'Feature' do
add 'BETA_UI'
add 'ADVANCED_SEARCH'
add 'LEGACY_DASHBOARD' , deprecated: 'Use new dashboard'
end
object 'User' do
field :enabled_features , 'Feature' , array: true
end
By default, enums only accept enum values (ADMIN). Enable string input globally:
# config/initializers/graphql.rb
Rails :: GraphQL . configure do | config |
config. allow_string_as_enum_input = true
end
With this enabled, both are valid:
createUser ( role : ADMIN ) # ✓ Enum value
createUser ( role : "ADMIN" ) # ✓ String (if enabled)
Validation
Enums validate input and output automatically:
GraphQL :: Role . valid_input? ( 'ADMIN' ) # => true
GraphQL :: Role . valid_input? ( 'GUEST' ) # => false
GraphQL :: Role . valid_output? ( 'ADMIN' ) # => true
Deprecated Values
Track deprecated values:
enum 'Role' do
add 'ADMIN'
add 'MODERATOR' , deprecated: 'Use ADMIN with limited permissions'
add 'LEGACY' , deprecated: true
end
GraphQL :: Role . all_deprecated_values
# => { "MODERATOR" => "Use ADMIN with limited permissions", "LEGACY" => true }
Inspection
Enums provide helpful inspection:
GraphQL :: Role . inspect
# => #<GraphQL::Enum Role (3) {ADMIN | SUPPORT | USER}>
GraphQL :: Episode . all_values
# => ["NEW_HOPE", "EMPIRE", "JEDI"]
Best Practices
Use enums for:
Fixed set of options (status, role, category)
Sort orders and directions
Filter criteria
Feature flags
Any predefined set of string values
Avoid enums for:
Dynamic values that change frequently
User-generated content
Large sets of values (use strings with validation)
Values that need localization at the GraphQL level
Enum values are always UPPERCASE in GraphQL, but the instance’s to_sym method returns lowercase symbols (:admin) for easier integration with Rails.
Type Checking
def create_user ( role: )
case role. to_sym
when :admin
User . create_admin!
when :support
User . create_support!
else
User . create!
end
end