enum設計で迷った話:string型 or integer型、どちらがいいのか。
こんにちは。
Railsを学習中の者です。
私が「通知モデル」を設計する際にenum
の型で迷った経緯と、調べてわかったことを備忘録としてまとめます。
通知機能の設計でこの問題に直面したので、実際の実装・調査・判断の流れをまとめてみました。
そもそもenumってどういう仕組みなのか
Railsのenum
は、モデル上でシンボルを定義することで、DBには数値や文字列を保存しつつ、コード上では人間が読みやすい形で扱える便利な機能です。
背景として通知の「種類」をenumで管理したいと思った
通知モデルに「通知の種類(kind)」という属性を追加しようとしたとき、以下のようなenumを使いたくなりました。
enum kind: { reminder: "reminder", warning: "warning" }
このとき悩んだのが、マイグレーションで kind カラムを string にするか、integer にするかという点です。
最初string型にしていた
私自身、もともと integer型
を使うつもりはありませんでした。
- 文字列のまま保存したほうが意味が直感的にわかる。
- enumを使い慣れていない初心者として扱いやすかった。
という初学者なりの理由からstring型 + enum
という構成を自然と選んでいました。
今回の実装(string型)
モデル
class Notification < ApplicationRecord
belongs_to :user
enum kind: {
reminder: "reminder",
warning: "warning"
}
validates :user_id, presence: true
validates :kind, presence: true, inclusion: { in: kinds.keys }
validates :active, inclusion: { in: [true, false] }
end
マイグレーション
class CreateNotifications < ActiveRecord::Migration[8.0]
def change
create_table :notifications do |t|
t.references :user, null: false, foreign_key: true
t.string :kind, null: false
t.boolean :active, default: true, null: false # 通知はデフォルトONで作成される
t.timestamps
end
end
end
string型かinteger型かで迷った点
通知の種類(kind)をenumで管理する際、以下の2パターンが存在します。
①integer型を使う場合
# モデル(Rails 7以降の新構文)
enum :kind, [:reminder, :warning]
# マイグレーション
t.integer :kind
- 保存される値は 0(reminder)や 1(warning)
- Rails 7以降の enum :kind, [:a, :b] 構文はこの形式が前提
- DB上では数字だけなので、内容を理解するにはコードを確認する必要あり
② string型を使う場合(今回採用)
# モデル
enum kind: {
reminder: "reminder",
warning: "warning"
}
# マイグレーション
t.string :kind
-
reminder
やwarning
といった文字列がそのままデータベースに保存されるため、内容を直接見て意味を理解しやすいという利点 - 一方で、
enum
で定義していない値が保存されるのを防ぐために、
inclusion: { in: kinds.keys }
のようなバリデーションを追加しておくといいらしい
最終的な判断:string型で採用
観点 | 理由 |
---|---|
可読性 | DBを見たときに意味がすぐわかる("reminder" など) |
開発・運用のしやすさ | SQLやログで確認する場面でも直感的 |
初学者としての安心感 | enum定義と保存値が一致していて混乱が少ない |
パフォーマンス | 差はほぼ気にしなくてOK(今回のスケールでは問題にならない) |
学んだこと
- Railsでは
enum
にstring
もinteger
も使えるが、新構文(配列形式)はinteger
前提のようです -
string
型を使う場合は、旧来のハッシュ形式({ name: "name" }
を使う - 可読性や運用面も含めて、状況に応じて設計判断することが大切
初学者として悩んだ末の選択でしたが、「なぜこの設計にしたのか」を言語化する経験がとても勉強になりました。
色々と書きましたが、間違えていましたら、申し訳ありません
参考
Railsガイド - Active Record Enum(公式)
Railsのenumをstringで使う方法
Railsのenumを使いこなす方法