ActiveRecord 和 Postgresql 的枚举类型

mar*_*ruz 3 postgresql activerecord ruby-on-rails

我按照SitePoint 的教程将模型属性设置为枚举值,Rails 从 4.1 开始支持该值。

我尝试添加季节枚举,而不是性别枚举。

这是我遇到的问题schema.db

# Could not dump table "semesters" because of following StandardError
#   Unknown type 'season' for column 'season'
Run Code Online (Sandbox Code Playgroud)

这是我的migration

class AddSeasonToSemesters < ActiveRecord::Migration[5.1]
  def up
    execute <<-SQL
    CREATE TYPE season AS ENUM ('fall', 'winter', 'spring', 'summer');
    SQL

    add_column :semesters, :season, :season, index: true
  end

  def down
    remove_column :semesters, :season

    execute <<-SQL
    DROP TYPE season;
    SQL
  end
end
Run Code Online (Sandbox Code Playgroud)

还有我的model文件:

class Semester < ApplicationRecord
  enum season: {
      fall: 'fall',
      winter: 'winter',
      spring: 'spring',
      summer: 'summer'
  }
end
Run Code Online (Sandbox Code Playgroud)

知道我做错了什么吗?任何方向将不胜感激,谢谢。

mu *_*ort 5

您需要从 切换db/schema.rbdb/structure.sql

根本问题是,它schema.rb是 ActiveRecord 所看到的数据库结构的表示,但 ActiveRecord 无法理解 PostgreSQL 所理解的很多内容(例如create typeCHECK 约束以及execute some_raw_sql迁移中语句中显示的其他内容)。你可以得到create type你想要的一切,但schema.rb你永远看不到它。

如果您想使用 ActiveRecord 无法理解的内容,那么您必须使用它db/structure.sql来存储数据库的结构。structure.sql按照数据库理解的方式存储数据库的结构,而不是按照 ActiveRecord 理解的方式存储。

切换很简单:

  1. 更新您的config/application.rb以包含config.active_record.schema_format = :sql.
  2. 执行 arake db:structure:dump以获得初始值db/structure.sql.
  3. 删除db/schema.rb从目录树和修订控制中
  4. 添加db/structure.sql到修订控制。
  5. 调整你的耙子习惯:
    • 使用db:structure:dump而不是db:schema:dump
    • 使用db:structure:load而不是db:schema:load

也就是说,我不确定 PostgreSQL 的本机enum类型与 ActiveRecord 的交互效果如何,因为我从未这样做过。ARenum字符串和整数之间的客户端转换,但PostgreSQLenum在数据库内部处理的,并且它们彼此不了解。可能会存在冲突,您需要确保它们彼此保持同步。