enumとは
integer型
やstring型
の1つであり、「enum型」
に該当する。
enum
とは、1つのカラムに指定した複数個の定数を保存できる様にする為のものである。
文字列と値を関係づけてプログラムの可読性を上げるとともに、データベースに格納される値が規定の範囲を超えることがないようにすることができる。
例えば、0が「応答待ち」、1が「リクエスト中」、2が「処理中」、3が「入力待ち」と設定して、 状態を保持する変数status
があったとする。
これをプログラム上で数値だけを扱っていると、「どの数値が何を表しているのか」が分からなくなってくる。そのため、定数定義するなどして、数値に名前を付けて可読性を上げるのために使われる。
「enum型」
ではその定義の中で名前を羅列すると、それらの名前に自動で値を割り当ててくれる。
大まかな特徴は以下の3つ。
・名前(文字列)のリストに一意の値が割り当てられる
・定義の順番通りに値が割り当てられ、追加や削除すると自動的に割り当て直される(値を指定することも可能)
・enum型の変数は、定義されている以外の値を受け付けない(例外が発生する)
enumの使い方
``Railsのenum```は、モデルに定義することができる型で、定義することで、データベースの特定のカラムの値(整数値)を、指定した文字列(シンボル)で扱うことができる。
まずenum
を使うために
1.テーブルにenum用のカラムを用意する
2.モデルにenumの定義をする必要がある。
user
に管理権限の有無を例に、
roleカラム
にて、0
であれば一般ユーザー・1
であれば管理者ユーザーとして権限を与える例でやっていく。
1.テーブルにenum用のカラムを用意する
まずはuserテーブル
にroleカラム
を追加する際には型を、Integer型
かboolean型
の2択になる。
◆integer型
2個以上の定数を紐付けたい場合は型はinteger型で定義。
◆boolean型
2個の定数を紐付けたい場合かつ真偽値を保存したい
時はboolean型で定義。
(enum
を設定しなくてもboolean型
だけで充分機能は実装できるのでenum
を設定する必要は特にないので、基本的にはinteger型
で良さそう)
今回はinteger型
での実装例として扱う。
class AddRoleToUsers < ActiveRecord::Migration[5.2]
def change
add_column :users, :role, :integer, default: 0, null: false
end
end
空白データは存在しない前提なので、null: false
にしdefault: 0(初期値には0)
を指定する。
2.モデルにenumの定義
class User < ApplicationRecord
#hashで定義する場合
enum role: { general: 0, admin: 1 }
# シンボル配列で定義する場合
enum role: [ :general, :admin]
# 文字配列で定義する場合
enum role: [ "general", "admin"]
end
基本的にどの方法で定義しても可能。特に大きな違いはないが、しいて挙げるならば下記の2つが違いになる。
・hashの定数と整数の紐付けは0から始めなくても良い
・配列で定義する方がインデックスが自動で定数と紐づいてくれるので、記述量が少なくすっきりしたコードになる
◆enumを定義する上での注意点
enumのカラム
を設定するときに気をつけないといけないことは、カラムに予約語を設定すること。
予約語とは、言語側(今回で言うとruby
)で既にこの単語は言語(ruby
)で使用しているから使わないで、という単語のこと。
例えばruby
ではnil
とは何もないという意味がある。これを変数で定義すると
nil = '何もない'
SyntaxError: (irb):1: Can't assign to nil
上記の様に、nil
は既にruby側
で定義しているので変数として定義できないというエラーが出る。
これはつまり、ruby側
でnil
という単語は何もないという意味で既に予約している(定義している)ので、変数としては使わないで、ということになる。この様に言語側で既に使うと予約してる単語を予約語と言う。
enum
は複数の定数を登録するので、カラム名をActiveRecord
で使用している予約語のtype
にしてしまいがちなので、予約語はカラム名として使えないためエラーになるので注意。
enumの便利なメソッド
・確認メソッド
今enumカラムに入っている定数が何なのか確認するメソッドのこと。
#あるuserが管理権限を持っているかどうか確認するとき
user.general?
=> false
user.admin?
=> true
user.test?
NoMethodError: undefined method `test?'
確認メソッドは上記の様に使用する。
モデルのインスタンスに対してインスタンス.定数名?
の形でenumカラムに指定した定数が入っていればtrue
が返ってきて、指定した定数が入っていなければfalse
が返ってくる。
そして登録していない定数であるuser.test?
に関しては、エラーが出る。
・更新メソッド
更新メソッドとは、enumカラムに入ってある定数を別の定数に更新するメソッドのこと。
モデルのインスタンスに対してインスタンス.定数名!
の形で使う。
あるuserに管理権限を付与するとき
user.role
=> "general"
user.admin!
UPDATE `users` SET `role` = 1,..省略
=>true
・定数リスト取得メソッド
定数リスト取得メソッドとは、モデルファイルのenum
に記載している複数個の定数リストを取得するメソッドのこと。
モデルクラス.enumカラム名の複数形
という形で使用。
User.roles
=> {"general"=>0, "admin"=>1}
enumの日本語対応
Railsには、enum
をi18n対応させるgem「enum_help」
が用意されているので、簡単に行うことができる。
手順
1.enum_helpのインストール
2.localeファイルの作成
1.enum_helpのインストール
Gemfileにgem 'enum_help'
と記載後、bundle install
を実施。
2.localeファイルの作成
config/locales/activerecord/ja.ymlファイル
を作成し、翻訳を記載。
ja:
activerecord:
enums:
user:
role:
general: 一般ユーザー
admin: 管理者
user
に対してrole_i18n
インスタンスメソッドを使うと、日本語化出来たかどうか確認ができる。
irb(main):001:0> User.roles_i18n
=> {"general"=>"一般", "admin"=>"管理者"}