如何在 Rails 3 的 Postgres 数据库中使用枚举? [关闭]

Posted

技术标签:

【中文标题】如何在 Rails 3 的 Postgres 数据库中使用枚举? [关闭]【英文标题】:How to use enum in a Postgres database in Rails 3? [closed] 【发布时间】:2011-11-12 08:06:44 【问题描述】:

PostgreSQL 在数据库中内置了enumerated types 的概念。

如何在 Rails 3 中实现一个包含使用枚举类型的列的表?您是否需要以某种方式在 PostgreSQL 中定义枚举?您如何创建执行此操作的数据库迁移?

在 Rails 3.07、Ruby 1.92p180、PostgreSQL 8.3 中工作。

【问题讨论】:

究竟是什么阻止了您通过迁移在 Postgresql 中添加此枚举,并在之后使用它? 【参考方案1】:

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迁移。)

【讨论】:

这意味着您永远无法执行 schema:load,因为它会破坏 shema.rb。对于 mysql,有 ruby​​gem-enum_column3 gem。不知道修改它以使其也适用于 postgres 有多难.. 感谢您提供的信息。我几乎从不使用ENUMs 或schema:load ;) 您没有任何测试?使用模式:加载。您的测试数据库枚举将改为字符串。 测试使用db:test:prepare,它克隆了开发数据库。它不关心schema:load 错误。 db:test:prepare 检查挂起的迁移并从 db/schema.rb 加载架构【参考方案2】:

除了上述答案之外,对于 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

【讨论】:

非常有趣。此外,如果 ActiveRecord 有一种方法可以自动将 ::my_enum 转换附加到特定的常量,那就太棒了。 @rewritten 可以让 Rails 自动转换它,请参阅github.com/rails/rails/pull/7324 中的点类型以供参考。如果您想向 Rails 提交 PR,我很乐意提供帮助(还需要 schema.rb 支持才能使其成为 master)。 我认为这是针对特定类型的,您是否建议使用一些代码来管理任意用户定义的类型或只是枚举?让我们继续推特,刚刚关注你...【参考方案3】:

您还可以将架构设置为使用原始 SQL 而不是 .rb 文件。如果您利用数据库的更高级功能(枚举、全文搜索、触发器、函数等)而不是简单地将其用作通用数据存储,这将使您的生活更轻松。

只需在 config/application.rb 中设置这一行

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

它会输出一个structure.sql文件,为你解决这个问题。

【讨论】:

以上是关于如何在 Rails 3 的 Postgres 数据库中使用枚举? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

如何将 Postgres 数据库从一个 Elastic Beanstalk 环境复制到另一个环境?我正在使用 Rails 5

Ruby On Rails Heroku Postgres数据库SSL连接

如何删除rails的postgres用户密码?

Postgres / Rails Active Record - 查询四舍五入的浮点值

如何使用 Postgres 在 Rails 中按天对记录进行分组

如何将 Rails 应用程序连接到主机上的 docker postgres