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

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

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

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

【问题讨论】:

  • 究竟是什么阻止了您通过迁移在 Postgresql 中添加此枚举,并在之后使用它?

标签: ruby-on-rails ruby-on-rails-3 postgresql enums database-migration


【解决方案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 enumsvalidates_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文件,为你解决这个问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-04
    • 2019-12-26
    • 2017-05-06
    • 2017-02-01
    • 1970-01-01
    • 2016-05-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多