-
-
Notifications
You must be signed in to change notification settings - Fork 17
Enum
Enum type manager. For each enum-type created on the database, it allows 2 behaviors: Single enum attribution, Array (Set-like) attribution. For Array attribution check the link. It creates a separated class to hold each enum set that can be used by multiple models, it also keeps the database consistent. The enum type is known to have a better performance against string- and integer-like enums. PostgreSQL Docs
First, you have to create the enum during your migration, since it's the database that holds the list of possible values.
create_enum :roles, %i(visitor manager admin)
Some other examples are:
# ['status_foo', 'status_bar']
create_enum :status, %i(foo bar), prefix: true
# 'foo_tst', 'bar_tst']
create_enum :status, %i(foo bar), suffix: 'tst'
You can also manage this type along other migrations, renaming, adding values, or deleting it.
# Rename enum by renaming the type it represents
rename_type :status, :content_status
# Adding values
add_enum_values :status, %i(baz qux) # To the end of the list
add_enum_values :status, %i(baz qux), prepend: true # At the beginning of the list
add_enum_values :status, %i(baz qux), after: 'foo' # After a certain value
add_enum_values :status, %i(baz qux), before: 'foo' # Before a certain value
add_enum_values :status, %i(baz qux), prefix: true # With type name as prefix
add_enum_values :status, %i(baz qux), suffix: 'tst' # With a specific suffix
# Deleting an enum by dropping the type it represents
drop_type :status
Once you've created the type, you can use it while creating your table in three ways
create_table :users do |t|
t.string :name
t.role :role # Uses the type of the column, since enum is a type
t.enum :status # Figures the type name from the column name
t.enum :last_status, subtype: :status # Explicit tells the type to be used
end
Each enum type loaded from the database will have its own class type of value, created under the enum.namespace
namespace.
Enum::Roles
# You can get a representative value from there
Enum::Roles.admin
# Or you can get the list of values
Enum::Roles.values
# Allows you to iterate over the values directly from the class
Enum::Roles.each do |role|
puts role
end
# You can use index-based references of a value
Enum::Roles.new(0) # #<Enum::Roles "visitor">
Enum::Roles.admin.to_i # 2
If you kept the enum.initializer
setting as false
, you have to go to each of your models and enable the functionality for each enum-type field. You don't need to provide the values since they will be loaded from the database. The method name is defined on enum.base_method
.
# models/user.rb
class User < ActiveRecord::Base
enum :role, :status
end
You are able to access the list of values trough the class that holds the enum:
User.roles
You can set the column value from String
, Symbol
, and Integer
:
user = User.new
user.role = 'admin' # #<Enum::Roles "admin">
user.role = :manager # #<Enum::Roles "manager">
user.role = 0 # #<Enum::Roles "visitor">
This allows you to compare values, or make questions about it:
other_user = User.new(role: :manager)
user = User.new(role: :manager)
user.role > :admin # false
user.role == 1 # true
user.role >= other_user.role # true
user.role.manager? # true
user.visitor? # false
The bang!
methods are controlled by the enum.save_on_bang
:
# The following will only perform a save on the database if enum.save_on_bang is set to true
user = User.new(role: :manager)
user.admin!
You can reach the I18n translations from three different ways, and the scopes are configured on enum.i18n_scopes
. On the third one, only the scopes on enum.i18n_type_scope
are used, that allows per-model customization.
user = User.new(role: :manager)
user.role.text # User's manager
user.role_text # User's manager
Enum::Roles.manager.text # Manager
When testing models or creating records using factories, Enum
provides an easy way to get a random value from the list of any enum types. Besides the normal User.roles.sample
, you can also use:
Enum.sample(:roles)
Can't find what you're looking for? Add an issue to the issue tracker.