Rails 7: PostgreSQLのカスタムenum型が使いやすくなった(翻訳)
PostgreSQLに組み込まれている列挙型のサポートは、Railsでも利用可能です。しかし、PostgreSQLの列挙型をActive Recordのマイグレーションで作成するのは面倒なので、列挙型を使おうとするとつらい思いをしがちです。
変更前
従来の方法では、以下のようにSQL文を直接実行してカスタム列挙型を作成していました。
# db/migrate/*_create_articles.rb
def up
execute <<-SQL
CREATE TYPE status AS ENUM ('draft', 'published', 'archived', 'trashed');
SQL
create_table :articles do |t|
t.column :current_status, :status
end
end
現場ではおそらく不便でしょう。
変更後
RailsとPostgreSQLを用いる開発では、PostgreSQLのカスタム列挙型の管理を少しでもましにするために、schema.rbの代わりにstructure.sqlを使うことがよくあります。
ありがたいことに、Rails 7にPostgreSQLカスタム列挙型のサポートが追加されました(#41469)。この変更によって導入された列挙型作成用のcreate_enum
メソッドとカラムへの追加用のt.enum
メソッドのおかげで、そうした軋轢が取り除かれます。列挙型はActiveRecord::Enum
との相性もよいので、これまで以上に手軽に利用できます。
def up
# 注意: 列挙型をDROPするメソッドはありません
create_enum :status, ["draft", "published", "archived", "trashed"]
change_table :articles do |t|
t.enum :current_status, enum_type: "status", default: "draft", null: false
end
end
上によって、列挙型の定義と列挙型カラムがschema.rbに追加されるので、testデータベースに読み込んで問題なく利用できます。
ActiveRecord::Schema.define(version: 2022_01_03_113555) do
# このデータベースをサポートするために必須の拡張がある
enable_extension "plpgsql"
# このデータベースで定義されるカスタム型
# 一部の型は他のデータベースエンジンで動かない可能性があることに注意
create_enum "status", ["draft", "published", "archived", "trashed"]
create_table "articles", force: :cascade do |t|
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.enum "current_status", default: "draft", null: false, enum_type: "status"
end
end
これは他のデータベースアダプタと互換性がないので注意が必要です。将来別のデータベースに乗り換えることになった場合は、手動で移行する必要があるでしょう。
概要
原著者の許諾を得て翻訳・公開いたします。
日本語タイトルは内容に即したものにしました。
なお、その後
drop_enum
がmainブランチにマージされました。参考: Add
drop_enum
command for Postgres by ghiculescu · Pull Request #45735 · rails/rails参考: 週刊Railsウォッチ20220822: マイグレーションにdrop_enumコマンドが追加(PostgreSQLのみ)