タイトルのとおりなのだけど、仕事でちょっとハマった話。
特定3種類の値だけを利用するフィールドを追加したくて、Railsのenumは使いつつ、DB上でもenumで型定義しておけば"固い"よなと思って、そういうテーブル定義をしようとした。 このあたりは前職のMySQLのテーブル定義においてそういうカラムがよくあったので、まぁポスグレでもできるだろうという感覚で調べ始めた。
軽く調べてみると、以下のような記事(翻訳もあった)があったり、
RailsGuidesにも「Active Record と PostgreSQL」のページに「1.7 列挙型(enumrated type)」の記載があった。
enumの型定義自体は create_table
などのDSLの中でできず、
execute <<-SQL CREATE TYPE article_status AS ENUM ('draft', 'published'); SQL
と、SQLを直接実行しているが、これがよく行われているやり方なのかなと理解した。
自分もそのように書いてみて db:migrate
と db:rollback
が問題なく実行できることを確認したのだが、あとからschema.rbに以下のようなメッセージが生成されていることに気がついた。
# Could not dump table #{TABLE名} because of following StandardError # Unknown type #{enum用に定義したtype名} for column #{enumを使いたかったカラム名}
というわけで、上に書いたようにRubyのDSLでPostgresのenumが定義できないために、schema.rbも生成できないと理解した。
あとから気づいたが、close済のissueもあった。
schema.rb can't support a few database specific constructions. You need to change the format to sql if you want to use those features.
とのことで、schema.rbでなくstructure.sqlを利用するようにしてあげれば、こういったmigration用のDSLで表現できないTABLE定義も利用できそうだ。
もしstrucuture.sqlを生成したいのであれば、config.active_record.schema_format
を :ruby
ではなく :sql
に変更すればよい。
ただし言わずもがな、ActiveRecordの抽象をひっぺがして特定RDBMSへの依存を高めることにはなるので、プロジェクトでの利害は考えた方がよいと思う。