What is enum?
Enum (short form of Enumeration) is a data type used to assign names to integral constants. The names are identifiers that behave as constants in language and makes a program easy to read and maintain.
ActiveRecord::Enum was introduced in Rails 4.1.
An enum is an attribute where the values map to
integers in the database and can be queried by name.
Enums also give us the ability to change the state of the
data very quickly.
This makes it easy to use enums in Rails
saves a lot of time by providing dynamic methods.
Creating database column for enum
In Rails, adding an enum to a model is pretty simple as adding an integer column to the table.
Let’s assume we have a Rails application that has a
A post can be drafted,
Instead of using these strings in the Post table
to denote its status,
we can use integers like
Post table already exists in our application
the DB migration to add
status as enum will look as below:
We have added the default value as 0 in the migration.
This means the post status will be
draft by default.
Various ways to define enum in model
We run the migration using
in our Post model,
we need to define the enum as shown in the below example.
The enum method expects the column attribute name which it should
the second parameter is a list of values a post status can have.
We can also use the
%i() format to declare enums.
Since we have used arrays for declaring enums,
draft will be mapped to 0 in the database,
published will be mapped to 1, and so on.
Instead of an array,
we can also pass a hash where the key will be
the values can be assigned as per the developer’s choice.
The recommended way is to use a hash instead of an array because if we change the order of the values, we will break the whole logic inside our Rails app.
How enum works
We can fetch all the enum values or a particular enum value using the pluralized form of the column name.
Creating a published post
For the First post where
status is not passed,
it gets set to
draft by default.
Even if the
status column stores integer value,
we can pass the symbol
:published as a value to the status key.
This is because Rails knows that the
status column is an enum,
and it replaces the values internally from symbol to integer.
Verifying the post status
Rails provide dynamic methods to verify the status of a particular post.
If we create a post
we usually verify by using
post.status == 'published'.
With an enum,
we can verify using enum helpers provided by Rails.
Updating a post status
Similar to verifying the post status using ?,
Rails enum provides a helper for updating the enum value.
Instead of using
we can use the ! method.
Working with scopes
Our Rails app
has a Post model with different statuses
and we would want to pull records only with a given status
sooner or later.
Rails has added dynamic methods to resolve this query.
To fetch all
we might use
query in our Rails controllers.
Instead of this,
we can use the
published method as scope on Post.
For every status,
we have in our enum,
Rails add a class method with the same name.
In our case,
for the Post model.
With Rails 6,
we can also add the negate condition to enum scopes.
To fetch all posts that are not
we can add the
not_ prefix to the
We can also disable these enum scopes by adding the
scopes: false option to the enum defined in the model.
Using the scope methods then will raise NoMethodError.
Prefixes and Suffixes
Sometimes the enum values might not be meaningful
it’s better to apply prefix or suffix to enum name.
Let’s take the User model in this case with the
enum in our application.
user.active? method can be precisely written as
user.active_status? and similar for other enum names.
To achieve this,
we can add
suffix: true as an option to enum.
We can use the updated dynamic methods for equality check, updating and querying on user object or model.
If we pass
the above methods will change to:
Suffixes are useful when a model has two columns
with enum values.
Let’s say our Post model has a
category column which is an enum
and can take
If we define these enums without prefix or suffix,
post.premium! will confuse developers which columns
these methods are referring to.
Instead, we can add prefix and suffix as per our requirement and call the methods accordingly.
Rails 7 introduced a new syntax for enum. For more details, please refer to our previous blog post.