Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

Rails 7: PostgreSQLのカスタムenum型が使いやすくなった(翻訳)

概要

原著者の許諾を得て翻訳・公開いたします。

日本語タイトルは内容に即したものにしました。

なお、その後drop_enumがmainブランチにマージされました。
参考: Add drop_enum command for Postgres by ghiculescu · Pull Request #45735 · rails/rails
参考: 週刊Railsウォッチ20220822: マイグレーションにdrop_enumコマンドが追加(PostgreSQLのみ)

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

これは他のデータベースアダプタと互換性がないので注意が必要です。将来別のデータベースに乗り換えることになった場合は、手動で移行する必要があるでしょう。

関連記事

Rails 7: insert_allとupsert_allで属性のエイリアスを指定可能になる(翻訳)


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。