A comprehensive guide to Rails enum
Tags: rails, webdev, beginners, ruby
Published: 2020-12-04 03:46:55

![Ruby on Rails logo](https://dev-to-uploads.s3.amazonaws.com/i/ouhu4gzgg8qzq6doy50s.png)

#What is `enum`?#

Enum is short for enumeration, a data type consisting of named elements, each having a different value. The enumerator names are usually identifiers that behave as constants in the language.

`ActiveRecord::Enum` was introduced in Rails 4.1. By declaring an enum attribute, you can map the values such as **strings** and **symbols** to **integers** in the database, and yet can query them by name. This means **it has the speed and efficiency of an integer and the flexibility of a string or a symbol**.
***

#When can we use `enum`?#

**When the values of the field are constants.** Let's say you create a `Book` model and it has a field of `genre`. You can map genre names to integers like: `{ fantasy: 0, adventure: 1, mystery: 2, romance: 3 }`
***

#How to implement `enum`?#

Let's keep using the `Book` model example.

###1.Add `genre` field to `books` as **integer**###
```ruby
class AddGenreToBooks < ActiveRecord::Migration[6.0]
  def change
    add_column :books, :genre, :integer
  end
end
```

###2.Add `genre` to the `Book` model###

There are two ways to declare enum:

* Using array
```ruby
# app/models/book.rb
class Book < ActiveRecord::Base
  enum genre: [ :fantasy, :adventure, :mystery, :romance ]
end
```
...or even simpler,
```ruby
# app/models/book.rb
class Book < ActiveRecord::Base
  enum genre: %i(fantasy adventure mystery romance)
end
```
For the syntax of `%i()` (percent strings), please refer to my blog post ["Refactoring checklist for beautiful Ruby code"](https://dev.to/junko911/refactoring-checklist-for-beautiful-ruby-code-175c)
* Using hash
```ruby
# app/models/book.rb
class Book < ActiveRecord::Base
  enum genre: { fantasy: 0, adventure: 1, mystery: 2, romance: 3 }
end
```

Using hash is a good option if you want to assign specific numbers to the values.
***

#Let's see how it works.#

###Query genre###

```ruby
# console
2.6.1 :001 > Book.genres # Check how the genre enum is defined
=> {"fantasy"=>0, "adventure"=>1, "mystery"=>2, "romance"=>3}
2.6.1 :002 > Book.genres[:adventure] # Check the identifier number of "adventure"
=> 1
2.6.1 :003 > Book.genres[:history] # If the genre doesn't exist, it returns nil
=> nil
```
###Create and update an instance###

```ruby
# console
2.6.1 :001 > book = Book.create(title: "The Lord of the Rings", genre: 0)
=> #<Book id: 1, title: "The Lord of the Rings", genre: "fantasy", created_at: "2020-12-03 03:27:05", updated_at: "2020-12-03 03:27:05">
2.6.1 :002 > book.genre # Check the genre
=> "fantasy"

# The following doesn't work when you use strings with spaces for enum.
2.6.1 :003 > book.adventure? # Check if the genre is "adventure"
=> false
2.6.1 :004 > book.adventure! # Update the genre
=> true
2.6.1 :005 > book.genre
=> "adventure"
```

###Enum in views###

The cool thing about enum is you can treat it as symbols or strings in controllers and views and don't need to worry it is actually integers in the database.

```ruby
# app/controllers/books_controller.rb
def index
  @books = Book.all
end

def new
  @book = Book.new
end
```

```ruby
# app/views/books/index.html.erb
<% @books.each do |book| %>
  <div><%= book.title %></div>
  <div><%= book.genre %></div>
<% end %>
```

```ruby
# app/views/books/new.html.erb
<%= form_for @book do |f| %>
  <%= f.select :genre, Book.genres.keys %>
  <%= f.submit %>
<% end %>
```
***

`ActiveRecord::Enum` is a cheaper way to store data as it is an integer in memory, but yet allows you to use all the ActiveRecord methods you know.