How to use enum attributes in Ruby on Rails

Dive into the world of enums to discover how they can streamline your code and make it more readable. Learn best practices, how to add and manage enum attributes, and take advantage of Rails' built-in features to efficiently manage finite sets of values in your models.

Enums, or enumerations, are an incredibly common way to represent options for an attribute of a model in Rails. If a model has an attribute-like status, it is often a string with predefined options. In Rails, you can represent this as an integer and automatically convert it to a string using built-in methods! This makes presenting options to a user as strings while storing these selections as a number straightforward and maintainable.

In this article, we'll discuss why you might want to use enums in your code, how to add an enum attribute to an existing table, how to create a new table with an enum, and how to use enums in your application.

Why enums are useful

Enums in Rails allow us to map a set of symbolic keys to specific integer values in the database. This makes them an efficient way to represent and store a limited set of values for an attribute, such as a status, without having to use strings or create additional tables mapping strings to integers. Using enums also brings consistency and readability to the code, making it easier for developers to understand the possible values of an attribute without having to dig through the database schema.

In addition to simplifying data representation and storage, enums also come with useful utility methods. For example, enums automatically generate scope methods for each value, making it easy to query and filter records based on the enum attribute. They also generate methods for each enum value, so the code can easily check the current value of an enum attribute in a more readable and expressive manner. Enums are often leveraged in form helpers, making presenting options in a form straightforward.

Adding an enum to an existing table

To add an enum attribute to an existing table in Rails, start by creating a new migration.

For example, if you're adding an attribute status to the model course, run the following:

rails generate migration AddStatusToCourse status:integer

If you want the attribute to have a default value, open the newly created migration in db/migrate and edit the add_column method call to have the default value you want:

add_column :courses, :status, :integer, default: 0

To apply the migration to your database, run the following:

rails db:migrate

Next, edit your model to declare the enum and its mappings of strings to integers.

class Course < ApplicationRecord
  enum status: {
    pending: 0,
    active: 1,
    archived: 2 
  }
end

That's it! You've added an attribute to your model and defined it as an enum; all that's remaining is to actually use the enum.

Creating an enum with a new database table

If you don't already have a model with which you'd like to use an enum, adding an enum attribute is as easy as any other attribute you'll need for that model. If you haven’t generated the course model, for example, you can begin by generating a new model.

rails generate model Course name:string status:integer

Open up your latest migration, and ensure it looks like this:

class CreateFamilies < ActiveRecord::Migration[7.0]
  def change
    create_table :users do |t|
      t.string  :name
      t.integer :status
    end
  end
end

Finally, run the migration:

rails db:migrate

Finally, add the enum definition to your model, as shown in the previous section:

class Course < ApplicationRecord
  enum status: {
    pending: 0,
    active: 1,
    archived: 2 
  }
end

Setting an enum value

Setting the value of an enum attribute of a model is readable, even though the data is saved as an integer.

In what is probably the most common method, you can set the value using the symbolic key:

course.status = :active
course.save

You can also set the value using the string representation of the symbolic key:

course.status = "active"
course.save

If you're initializing the object, you can set the value during initialization:

course = Course.new(status: :active)
course.save

You can even use the bang methods for each option generated by the enum:

course = Course.new
course.active!

These are some of the most common ways to set the value of an enum attribute in Rails. It's generally recommended to use the symbolic keys or their string representation rather than the integer directly, as they make your code more readable and expressive.

Checking an enum value

While you can technically check the integer value of an enum, Rails generates predicate methods that make checking the value of an enum easy and readable:

course = Course.new(status: :active)

course.pending?  # returns false
course.active?   # returns true
course.archived? # returns false

You can also compare the enum attribute directly with a symbolic key or even its string representation:

course = Course.new(status: :active)

course.status == :active   # returns true
course.status == "active"  # also returns true!

There are more ways to compare enum values, but these are the most common.

Conclusion

Overall, enums in Ruby on Rails offer a clean and efficient way to represent a finite set of values for a model attribute. Their integration with Rails' built-in features, such as scope and predicate methods, makes them a powerful and convenient choice for managing such attributes. In turn, this leads to improved code readability, maintainability, and a more enjoyable development experience.

Leaning on Rails conventions when using enums ensures the seamless translation of symbols into stored integer values and affords straightforward methods for checking those values.

What to do next:
  1. Try Honeybadger for FREE
    Honeybadger helps you find and fix errors before your users can even report them. Get set up in minutes and check monitoring off your to-do list.
    Start free trial
    Easy 5-minute setup — No credit card required
  2. Get the Honeybadger newsletter
    Each month we share news, best practices, and stories from the DevOps & monitoring community—exclusively for developers like you.
    author photo

    Jeffery Morhous

    Jeff is a Software Engineer working in healtcare technology using Ruby on Rails, React, and plenty more tools. He loves making things that make life more interesting and learning as much he can on the way. In his spare time, he loves to play guitar, hike, and tinker with cars.

    More articles by Jeffery Morhous
    Stop wasting time manually checking logs for errors!

    Try the only application health monitoring tool that allows you to track application errors, uptime, and cron jobs in one simple platform.

    • Know when critical errors occur, and which customers are affected.
    • Respond instantly when your systems go down.
    • Improve the health of your systems over time.
    • Fix problems before your customers can report them!

    As developers ourselves, we hated wasting time tracking down errors—so we built the system we always wanted.

    Honeybadger tracks everything you need and nothing you don't, creating one simple solution to keep your application running and error free so you can do what you do best—release new code. Try it free and see for yourself.

    Start free trial
    Simple 5-minute setup — No credit card required

    Learn more

    "We've looked at a lot of error management systems. Honeybadger is head and shoulders above the rest and somehow gets better with every new release."
    — Michael Smith, Cofounder & CTO of YvesBlue

    Honeybadger is trusted by top companies like:

    “Everyone is in love with Honeybadger ... the UI is spot on.”
    Molly Struve, Sr. Site Reliability Engineer, Netflix
    Start free trial