PostgreSQL在数据库中内置了enumerated types的概念。
如何实现一个包含在Rails 3中使用枚举类型的列的表?你需要以某种方式在PostgreSQL中定义枚举吗?你怎么能创建一个这样做的数据库迁移?
使用Rails 3.07,Ruby 1.92p180,PostgreSQL 8.3。
答案 0 :(得分:13)
Rails不支持开箱即用的ENUM
数据类型。这是因为并非所有数据库都支持该数据类型。我发现处理ENUM
值的常用方法是在数据库中手动创建枚举列(在您的情况下为PostgreSQL),并在Rails应用程序中将其作为string
列处理。然后,使用validates_inclusion_of验证程序强制使用允许的值。
validates_inclusion_of :gender, :in => [ "male", "female" ]
在迁移中使用本机SQL添加枚举字段:
class AddEnumType < ActiveRecord::Migration
def up
execute ".." # your native PostgreSQL queries to add the ENUM field
end
end
编辑(2014年6月)
Rails 4.1现在supports enums。 validates_inclusion_of
现在可以更改为:
enum gender: [ :male, :female ]
(但是,底层数据库本身仍然不支持此功能,因此仍需要本机SQL迁移。)
答案 1 :(得分:9)
您还可以将架构设置为使用原始SQL而不是.rb文件。如果您正在利用数据库的更高级功能(枚举,全文搜索,触发器,函数等),而不是简单地将其用作通用数据存储,这将使您的生活更轻松。
只需在config / application.rb中设置此行
即可# Use SQL for the schema due to many database specific settings
config.active_record.schema_format = :sql
它将输出一个可以解决该问题的structure.sql文件。
答案 2 :(得分:3)
除了上述答案,对于Rails 4(可能还有3.2),您可以这样做以避免“无效OID”类型警告:
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::OID.alias_type 'my_enum_type', 'text'
查询时,您还需要将字符串转换为您的类型,例如
scope :my_enum_value_is, ->(value){
where('my_enum_value = ?::my_enum_type', value)
}
您还需要修补列解析器:
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_type
end