Skip to main content
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:
# 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:
Star Wars Episodes
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
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

As Input Arguments

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 Example
mutation {
  createUser(name: "John Doe", role: ADMIN) {
    id
    name
    role
  }
}
Response
{
  "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

to_s
String
Returns the plain string value: "ADMIN"
to_sym
Symbol
Returns a lowercase symbol: :admin
to_i
Integer
Returns the index position (0-based): 0
valid?
Boolean
Checks if the value is valid for this enum
deprecated?
Boolean
Returns true if the value has a deprecated directive
deprecated_reason
String | nil
Returns the deprecation reason if deprecated
description
String | nil
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

String Input Support

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
  • Arguments - Use enums as argument types
  • Fields - Use enums as field types
  • Scalars - Alternative for open-ended string values
  • Directives - Attach to enum values

Build docs developers (and LLMs) love