11
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Railsでのenumの使いどころと使い方について

Last updated at Posted at 2019-03-23

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を追加しているだけ)

/db/schema.rb
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を使い、単語と数値の紐づけを行っています。

/app/models/task.rb
class Task < ApplicationRecord
  enum progress: {
    waiting: 0,
    start: 1,
    processing: 2,
    done: 3
  }
end

動きを確認

まずはインスタンス作成

.irb
irb(main):001:0> task1 = Task.new
=> #<Task id: nil, progress: "waiting", created_at: nil, updated_at: nil>

マイグレーションファイルに定義しているとおり、デフォルトはwaiting

.irb
irb(main):010:0* task1.progress
=> "waiting"

progressに数値の1を代入するとstartとして認識されます

.irb
irb(main):029:0* task1.progress = 1
=> 1
irb(main):030:0> task1.progress
=> "start"

他のタスクとの進捗比較

もうひとつインスタンスを作成します。

.irb
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
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
```

# 感想
単語としても数値としても扱えるのは便利だけど数値として扱うときが若干めんどくさい。というかすげぇめんどくさい。

以上です。
11
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?