LoginSignup
5
2

More than 5 years have passed since last update.

ActiveRecordで普通のEnum型カラムを作成する

Last updated at Posted at 2018-07-19

はじめに

 ActiveRecordでEnumカラムを実現しようとすると、一般的にはモデルにシンボル配列を定義して、カラム自体は数値型にする場合が多いようです。しかし、このやり方では以下の問題が発生します。

  • 可読性が著しく落ちる
    • ツールを利用してテーブルを閲覧しても、カラムの値が何を意味しているかわからない
  • データベースを利用する為の情報が、アプリケーション(モデル)とデータベースに分離されてしまう
  • データベースが、このActiveRecordを利用したアプリケーションに依存してしまう
    • 特に、rubyを使わないアプリケーションからこのデータベースを利用する際に問題が生じる

 一般に、データベースはアプリケーションより寿命が長く、また昨今では収集したデータをpythonで分析することも少なくない為、ActiveRecordにデータベースの構造を左右されたくありません。よって、意地でもEnum型のカラムを作りたいと思います。なお、データベースはMySQLを利用します。

環境

バージョン
ruby 2.5.1
ActiveRecord 5.1.5
MySQL 5.7.20

手順

 といっても、やることはActiveRecord::ConnectionAdapters::TableDefinition#column(name, type)を利用して、typeに部分的なSQLを渡すだけ。

# samplesテーブルの作成
create_table 'samples', id: :integer, unsigned: true, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4" do |t|
    t.string 'name', limit: 100, default: '', null: false
    # こんな感じでEnum型カラムを定義できる
    t.column 'status', "ENUM ('none', 'failed', 'succeeded') DEFAULT 'none' NOT NULL"
    t.datetime 'created_at'
    t.datetime 'updated_at'
end

 挿入/参照する場合、通常の文字列として利用できます。定義されていない文字列を挿入した場合、ActiveRecord::StatementInvalidが送出されます。

# モデルを定義
class Sample < ActiveRecord::Base
end

# 挿入
Sample.transaction do
  model = Sample.create(name: 'Enoch', status: 'failed')
  model.save! if model.valid?
end

# 参照
res = Sample.where(status: 'failed').last
puts res.name # `Enoch`
5
2
1

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
5
2