enumとは
- 日本語で列挙型
- 値に意味をもたせてわかりやすくする
- 不正な値を入れないようにする
- Railsではモデルで使う
今回はRailsを使います。Rubyで同じようなことはできるようですが、enumとしての機能はRubyには用意されていないみたいです。
enumを使いたい状況
中身は何でもいいですが、ある処理があるとして、その処理の流れを
処理開始待ち(waiting)->処理開始(start)->処理中(processing)->処理終了(done)
という流れとします。
文字列型変数[progress]など作成してそのまま「waiting」とか「start」とか入れることもできますが、
数値型変数progress
で管理すれば、進捗の進み具合を数値と比較して確認することもできます。
(progressが1より高ければ処理開始(satart)までは進んでいる、など)
ただし、数字で管理すると困ることがあります。それは
「あれ、1ってwaitingだっけ?startだっけ?」のように数字を見てその意味を忘れてしまうとコードを読むときに非常に読みづらくなります。
enumのかっこいいところ
そこでenumを使って数字に意味をもたせることで解決できるのです。上記の例に当てはめてみると
progressカラム(integer型)
- waiting : 0
- start : 1
- processing : 2
- done : 3
をそれぞれ紐づけます。すると、progressカラムにwaitingを入れたら実際にはprogressカラムに0がデータとして入ります。
人間からみたら意味を持った文字を入れておきながら、DBでは数字で管理できるということです。
また、モデルのステータス管理で想定外の値をバリデーション等で束縛することもできます。
実際のコード
schema.rbの中身はこれです。
(taskモデルにinteger型のカラムprogress
を追加しているだけ)
ActiveRecord::Schema.define(version: 2019_03_23_024106) do
create_table "tasks", force: :cascade do |t|
t.integer "progress", default: 0
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
end
app/models/task.rbの中身はこれです。
ここでenumを使い、単語と数値の紐づけを行っています。
class Task < ApplicationRecord
enum progress: {
waiting: 0,
start: 1,
processing: 2,
done: 3
}
end
動きを確認
まずはインスタンス作成
irb(main):001:0> task1 = Task.new
=> #<Task id: nil, progress: "waiting", created_at: nil, updated_at: nil>
マイグレーションファイルに定義しているとおり、デフォルトはwaiting
irb(main):010:0* task1.progress
=> "waiting"
progress
に数値の1を代入するとstart
として認識されます
irb(main):029:0* task1.progress = 1
=> 1
irb(main):030:0> task1.progress
=> "start"
他のタスクとの進捗比較
もうひとつインスタンスを作成します。
irb(main):031:0> task2 = Task.new
=> #<Task id: nil, progress: "waiting", created_at: nil, updated_at: nil>
task1はtask2よりも進捗(progress)が進んでいるかの確認
数値として比較する場合は、メソッド[カラム名]_before_type_cast
が必要になるみたいです。
irb(main):080:0* task1.progress
=> "start"
irb(main):081:0> task2.progress
=> "waiting"
irb(main):082:0> task1.progress_before_type_cast > task2.progress_before_type_cast
=> true
```
# 感想
単語としても数値としても扱えるのは便利だけど数値として扱うときが若干めんどくさい。というかすげぇめんどくさい。
以上です。