loading...

How to handle Enum in ActiveRecord

konyu profile image @kon_yu ・2 min read

Overview

How to store values in models that inherit from ActiveRecord, and which validations are responded to when you enter a value.

Prerequisites.

Rails: 5.2
Ruby: 2.6.1

main topic.

Sample User Table Definitions

create_table :users do |t|
  t.string :name
  t.integer :state
  t.timestamps
end

Defining the user model

There's a variation of the empty character check for name.

class User < ApplicationRecord
  validates :name, presence: true
  enum state: { show: 0, hide: 1 }
end

Take one model and explain it based on it.

> u = User.first
  User Load (0.2ms) SELECT "users". * FROM "users" ORDER BY "users"." "id" ASC LIMIT ? id" ASC LIMIT ?  [["LIMIT", 1]]]
=> #<User id: 2, name: "Test 1", created_at: "2019-01-29 03:56:08", updated_at: "2019-03-11 02:52:09", state: "hide">

If you simply output state, you will see the string defined by enum instead of the number stored in the DB.

> u.state.
=> "hide"

Assignment Method

You can substitute symbols defined by enum, strings, or numbers actually stored in the DB.

In the case of symbols

u.state = :hide
=> :hide
irb(main):038:0> u.state
=> "hide"

In the case of a string

u.state = "show"
=> "show"
irb(main):046:0> u.state
=> "show"

In the case of numbers

> u.state = 0
=> 0
> u.state.
=> "show"

Assigning an undefined value

If you try to assign a number outside the range defined by enum, you get an error.

> u.state = "show2"
ArgumentError ('show2' is not a valid state)

irb(main):047:0> u.state = "show2"
Traceback (most recent call last):
        1: from (irb):47
ArgumentError ('show2' is not a valid state)

> u.state = :show2
ArgumentError ('show2' is not a valid state)

> u.state = 2
ArgumentError ('2' is not a valid state)

Refer to the actual stored value

You can use u.state for debugging or testing to check which value is actually stored.
Use read_attribute_before_type_cast or attribute_name_before_type_cast.

> u.state.
=> "hide"

 u.read_attribute_before_type_cast(:state)
=> 1
irb(main):070:0> u.state_before_type_cast
=> 1

Discussion

pic
Editor guide