Home > Articles > Web Development

  • Print
  • + Share This
This chapter is from the book

This chapter is from the book

9.7 Enums

One of the newest additions to Active Record introduced in Rails 4.1 is the ability to set an attribute as an enumerable. Once an attribute has been set as an enumerable, Active Record will restrict the assignment of the attribute to a collection of predefined values.

To declare an enumerable attribute, use the enum macro-style class method, passing it an attribute name and an array of status values that the attribute can be set to.

1 class Post < ActiveRecord::Base
2   enum status: %i(draft published archived)
3   ...
4 end

Active Record implicitly maps each predefined value of an enum attribute to an integer; therefore, the column type of the enum attribute must be an integer as well. By default, an enum attribute will be set to nil. To set an initial state, one can set a default value in a migration. It’s recommended to set this value to the first declared status, which would map to 0.

1 class CreatePosts < ActiveRecord::Migration
2   def change
3     create_table :posts do |t|
4       t.integer :status, default: 0
5     end
6   end
7 end

For instance, given our example, the default status of a Post model would be “draft”:

>> Post.new.status
=> "draft"

You should never have to work with the underlying integer data type of an enum attribute, as Active Record creates both predicate and bang methods for each status value.

 1 post.draft!
 2 post.draft?       # => true
 3 post.published?   # => false
 4 post.status       # => "draft"
 6 post.published!
 7 post.published?   # => true
 8 post.draft?       # => false
 9 post.status       # => "published"
11 post.status = nil
12 post.status.nil?  # => true
13 post.status       # => nil

Active Record also provides scope methods for each status value. Invoking one of these scopes will return all records with that given status.

# Post Load (0.1ms)  SELECT "posts".* FROM "posts"
  WHERE   "posts"."status" = 0

With the addition of the enum attribute, Active Record finally has a simple state machine out of the box. This feature alone should simplify models that had previously depended on multiple boolean fields to manage state. If you require more advanced functionality, such as status transition callbacks and conditional transitions, it’s still recommended to use a full-blown state machine like state_machine.10

  • + Share This
  • 🔖 Save To Your Account