How to use enum in a Postgres database in Rails 3? [closed] How to use enum in a Postgres database in Rails 3? [closed] postgresql postgresql

How to use enum in a Postgres database in Rails 3? [closed]


Rails does not support the ENUM datatype out of the box. This is because not all databases support it that datatype. I found that a common way of dealing with ENUM values is to manually create the enum column in your database (PostgreSQL in your case), and deal with it as a string column in your Rails application. Then, use the validates_inclusion_of validator to force the use of the allowed values.

validates_inclusion_of :gender, :in => [ "male", "female" ]

And use native SQL in your migration to add the enum field:

class AddEnumType < ActiveRecord::Migration  def up    execute ".." # your native PostgreSQL queries to add the ENUM field  endend

edit (June 2014)

Rails 4.1 now supports enums. The validates_inclusion_of can now be changed to:

enum gender: [ :male, :female ]

(However, this is still not natively supported by the underlying database, so the native SQL migration is still needed.)


You can also set schema to use raw SQL instead of a .rb file. If you're leveraging more advanced features of a database (enums, full text search, triggers, functions, etc) rather than simply using it as a generic datastore this will make your life easier.

Just set this line in your config/application.rb

# Use SQL for the schema due to many database specific settingsconfig.active_record.schema_format = :sql

It will output a structure.sql file that will solve that problem for you.


In addition to the above answers, for Rails 4 (and possibly 3.2) you can do this to avoid "Invalid OID" type warnings:

ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::OID.alias_type 'my_enum_type', 'text'

When querying, you will also want to convert the string to your type, for example

scope :my_enum_value_is, ->(value){   where('my_enum_value = ?::my_enum_type', value) }

You'll also want to patch the column parser:

class ActiveRecord::ConnectionAdapters::Column  private  def simplified_type_with_my_enum_type(field_type)    if field_type == 'my_enum_type'      field_type.to_sym    else      simplified_type_without_my_enum_type(field_type)    end  end  alias_method_chain :simplified_type, :my_enum_typeend