Подтвердить что ты не робот

Как использовать перечисление в базе данных Postgres в Rails 3?

PostgreSQL имеет концепцию перечисляемых типов, встроенных в базу данных.

Как бы вы реализовали таблицу со столбцом, который использует перечисляемый тип в Rails 3? Вам нужно каким-то образом определить перечисление в PostgreSQL? Как можно создать миграцию базы данных, которая делает это?

Работает в Rails 3.07, Ruby 1.92p180, PostgreSQL 8.3.

4b9b3361

Ответ 1

Rails не поддерживает тип данных ENUM из коробки. Это связано с тем, что не все базы данных поддерживают этот тип данных. Я обнаружил, что общий способ использования значений ENUM - это вручную создать столбец перечисления в вашей базе данных (PostgreSQL в вашем случае) и обработать его как столбец string в вашем приложении Rails. Затем используйте 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

edit (июнь 2014 года)

Rails 4.1 теперь поддерживает перечисления. Теперь параметр validates_inclusion_of можно изменить на:

enum gender: [ :male, :female ]

(Тем не менее, эта поддержка по-прежнему не поддерживается базовой базой данных, поэтому миграция на родном SQL по-прежнему необходима.)

Ответ 2

Вы также можете настроить схему на использование raw SQL вместо файла .rb. Если вы используете более сложные функции базы данных (перечисления, полнотекстовый поиск, триггеры, функции и т.д.), А не просто использовать ее в качестве общего хранилища данных, это упростит вашу жизнь.

Просто установите эту строку в файле config/application.rb

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

Он выведет файл structure.sql, который решит эту проблему для вас.

Ответ 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