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