14

Rails3.1.1をPostgreSQL9.1とearthdistanceモジュールで使用しています。異なる場所間の距離を正しく計算できるようにするために、テーブルにearthタイプの列を設定しました。branches

私が今経験している問題は、このテーブルを使用するRailsアプリケーションが地球のタイプを理解していないため、これを取得していることですdb/schema.rb

#次のStandardErrorのため、テーブルの「ブランチ」をダンプできませんでした
#列'location'の不明なタイプ'earth'

これは、schema.rbからテストデータベースを作成できないため、問題があります。

このタイプをARに追加したり、その列を無視させたりするにはどうすればよいですか?

4

3 に答える 3

18

誰かがこれに遭遇する可能性があるもう1つのケースは、カスタムタイプ(列挙型)をPostgreSQLに挿入する場合です。これを実行してもSQLダンパーを使用せずにschema.rbをダンプしたい場合は、カスタムデータベースタイプをアダプターの有効なタイプのリストに追加できます。


アップデート2021-08-13:コメント投稿者は、以下の私の提案よりも簡単な方法があるかもしれないと指摘しています。

ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::NATIVE_DATABASE_TYPES[:my_custom_type] = { name: "my_custom_type_name" } 

元の提案

たとえば、とがCustomerあり、postgresのネイティブ列挙型を使用したいとしますstatuspriority移行では手動でセットアップを行う必要があり、Railsがスキーマを生成するのに役立つ初期化子が必要になります。

移行

class CreateCustomers < ActiveRecord::Migration[5.2]

  def up
    execute <<-SQL
      CREATE TYPE type_status AS ENUM ('active', 'inactive');
      CREATE TYPE type_priority AS ENUM ('high', 'medium','low');
    SQL

    create_table :customers do |t|
      t.string :name
      t.column :status, :type_status
      t.column :priority, :type_priority
    end
  end

  def down
    drop_table :customer_addresses
    execute <<-SQL
      DROP TYPE status;
      DROP TYPE priority;
    SQL
  end
end

イニシャライザ。

# config/initializers/postres_custom_enum_types.rb

# Following only needed if the adapater isn't loaded for some reason - e.g. 
# if you have no models in your app. 
require "active_record/connection_adapters/postgresql_adapter"

module ActiveRecord
  module ConnectionAdapters
    if const_defined?(:PostgreSQLAdapter)
      class PostgreSQLAdapter
        NATIVE_DATABASE_TYPES.merge!(
          enum:    { name: 'enum' },
          # there is a chance the above causes conflicts in some cases, you can
          # always be more explicit and actually use your type or names (I am not looking up which)
          # type_priority:    { name: 'enum' }
        )
      end
    end
  end
end

このソリューションの検証

これは、DBに表示されるものです。

enum_in_db_development=# INSERT INTO customers VALUES (1, 'Mario','active','high');
INSERT 0 1
enum_in_db_development=# INSERT INTO customers VALUES (1, 'Mario','active','notthere');
ERROR:  invalid input value for enum type_priority: "nothere"
LINE 1: INSERT INTO customers VALUES (1, 'Mario','active','notthere')
                                                          ^
enum_in_db_development=# SELECT enum_range(NULL::type_priority);
    enum_range     
-------------------
 {high,medium,low}
(1 row)

私の解決策についてのメモ:

  • PostgreSQLAdpater私が使用している静的分析gemがいくつかのAR依存関係(特にgem)を部分的にロードする方法のために、存在を確認していますannotate
  • NATIVE_DATABASE_TYPESの元の定義のソースは、rails6です。

これに遭遇した背景:Rails 5.0.xでこれが発生した場合、移行は正常に実行されましdb:test:prepareたが、またはを実行しようとするとテスト環境が失敗しましたdb:reset。これをスキーマダンプの問題まで追跡するのにかなりの時間がかかりました。

于 2017-08-01T06:24:24.457 に答える
10

これを試して:

config/application.rbを変更します

config.active_record.schema_format = :sql

これにより、出力形式がネイティブのPostgreSQL SQL形式に変更され、schema.rbが無効になり、新しいファイルが生成されます/db/config/structure.sql

于 2014-07-22T05:41:55.083 に答える
4

このページにアクセスする人のために、誰かがこれを使いやすい宝石に実装しました。

これは、移行ファイルとモデルファイルがそれぞれどのように見えるかです。

# 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

于 2020-05-28T18:48:28.367 に答える