Пользовательский тип базы данных в ActiveRecord

Я использую Rails 3.1.1 с PostgreSQL 9.1 и модулем earthdistance. Чтобы правильно рассчитать расстояние между различными точками, я настроил столбец с earth введите мой branches Таблица.

Проблема, с которой я сейчас сталкиваюсь, состоит в том, что мое Rails-приложение, которое использует эту таблицу, не понимает тип земли, и поэтому я получаю это в своем db/schema.rb:

# Не удалось создать дамп "ветвей" таблицы из-за следующей ошибки StandardError
# Неизвестный тип 'земля' для столбца 'местоположение'

Это проблематично, поскольку теперь я не могу создать свою тестовую базу данных из schema.rb.

Как я могу добавить этот тип в AR или заставить его игнорировать этот столбец?

2 ответа

Решение

Попробуй это:

Измените свой config/application.rb

config.active_record.schema_format = :sql

Это изменит выходной формат на собственный формат PostgreSQL SQL, schema.rb будет отключен и будет создан новый файл /db/config/structure.sql

Другой случай, когда кто-то может столкнуться с этим, - это вставка ваших пользовательских типов (перечислений) postgres в postgresql. Если вы делаете это и по-прежнему хотите использовать Ruby для вашего schema.rb, вы можете добавить пользовательские типы баз данных в список допустимых типов адаптера.

Например, скажем, у вас есть миграция, как это, с address_type а также address_status,

class CreateAddresses < ActiveRecord::Migration
  def up

    execute <<-SQL
      CREATE TYPE address_status AS ENUM ('active', 'archived');
      CREATE TYPE address_type AS ENUM ('billing', 'shipping');
    SQL

    create_table :customer_addresses do |t|
      # bla bla
      t.column :address_type, :address_type
      t.column :status, :address_status

      t.timestamps null: false
    end
  end

  def down
    drop_table :customer_addresses
    execute <<-SQL
      DROP TYPE address_type;
      DROP TYPE address_status;
    SQL
  end

end

Затем создайте инициализатор или добавьте нечто подобное в ваш application.rb:

# config/initializers/postres_enum_custom_types.rb
module ActiveRecord
  module ConnectionAdapters
    if const_defined?(:PostgreSQLAdapter)
      class PostgreSQLAdapter
        NATIVE_DATABASE_TYPES.merge!(
          address_status:  { name: 'character varying' },
          address_type:    { name: 'character varying' }
        )
      end
    end
  end
end

Примечания о моем решении:

  • Я проверяю существование PostgreSQLAdpater из-за того, что гем статического анализа, который я использую, частично загружает некоторые зависимости AR - в частности, гем annotate,
  • Источник для оригинального определения здесь.

Предыстория моего столкновения с этим: когда это случилось со мной в rails 5.0.x, миграция прошла нормально, но тогда моя тестовая среда потерпела неудачу при попытке запустить db:test:prepare или же db:reset, Мне потребовалось много времени, чтобы отследить это до проблемы с дампом схемы.

Для всех, кто заходит на эту страницу, кто-то реализовал это в виде простого в использовании драгоценного камня.

Так будут выглядеть файлы миграции и модели соответственно

# migration
class CreatePerson < ActiveRecord::Migration
  def change
    create_enum :mood, %w(happy great never_better)

    create_table :person do |t|
      t.enum :person_mood, enum_name: :mood
    end
  end
end

# model
class Person < ActiveRecord::Base
  enum mood: { happy: 'happy', great: 'great', never_better: 'never_better' }
end

https://github.com/bibendi/activerecord-postgres_enum

Другие вопросы по тегам