479 Stimmen

Wie gehe ich mit zu langen Indexnamen in einer Ruby on Rails ActiveRecord-Migration um?

Ich versuche, einen eindeutigen Index hinzuzufügen, der aus den Fremdschlüsseln von vier zugehörigen Tabellen erstellt wird:

add_index :studies,
  ["user_id", "university_id", "subject_name_id", "subject_type_id"],
  :unique => true

Die Beschränkung des Datenbanknamens führt dazu, dass die Migration fehlschlägt. Hier ist die Fehlermeldung:

Der Indexname 'index_studies_on_user_id_and_university_id_and_subject_name_id_and_subject_type_id' in der Tabelle 'studies' ist zu lang; das Limit beträgt 64 Zeichen

Wie kann ich das handhaben? Kann ich einen anderen Indexnamen angeben?

8voto

whatapalaver Punkte 795

Leider hat keiner dieser Lösungen für mich funktioniert. Vielleicht weil ich belongs_to in meiner create_table-Migration für eine polymorphe Association verwendet habe.

Ich werde meinen Code unten hinzufügen und einen Link zur Lösung, die mir geholfen hat, falls jemand anderes darauf stößt, wenn er nach 'Index name is too long' in Verbindung mit polymorphen Verknüpfungen sucht.

Der folgende Code hat bei mir NICHT funktioniert:

def change
  create_table :item_references do |t|
    t.text :item_unique_id
    t.belongs_to :referenceable, polymorphic: true
    t.timestamps
  end
  add_index :item_references, [:referenceable_id, :referenceable_type], name: 'idx_item_refs'

Dieser Code hat bei mir FUNKTIONIERT:

def change
  create_table :item_references do |t|
    t.text :item_unique_id
    t.belongs_to :referenceable, polymorphic: true, index: { name: 'idx_item_refs' }

    t.timestamps

Hier ist die SO-Frage und Antwort, die mir geholfen hat: https://stackoverflow.com/a/30366460/3258059

5voto

Jerph Punkte 4542

Ich habe ein Projekt, das Generatoren viel verwendet und brauchte, dass dies automatisch passiert, also habe ich die index_name-Funktion aus dem Rails-Quellcode kopiert, um sie zu überschreiben. Ich habe das in config/initializers/generated_index_name.rb hinzugefügt:

# Indizes kürzer machen für postgres
require "active_record/connection_adapters/abstract/schema_statements"
module ActiveRecord
  module ConnectionAdapters # :nodoc:
    module SchemaStatements
      def index_name(table_name, options) #:nodoc:
        if Hash === options
          if options[:column]
            "ix_#{table_name}_on_#{Array(options[:column]) * '__'}".slice(0,63)
          elsif options[:name]
            options[:name]
          else
            raise ArgumentError, "Sie müssen den Indexnamen angeben"
          end
        else
          index_name(table_name, index_name_options(options))
        end
      end
    end
  end
end

Es erstellt Indexe wie ix_assignments_on_case_id__project_id und kürzt sie einfach auf 63 Zeichen, wenn sie immer noch zu lang sind. Das wird immer noch nicht eindeutig sein, wenn der Tabellenname sehr lang ist, aber Sie können Komplikationen hinzufügen, wie das separate Kürzen des Tabellennamens von den Spaltennamen oder tatsächlich auf Eindeutigkeit prüfen.

Hinweis: Das ist aus einem Rails 5.2-Projekt; wenn Sie sich dazu entscheiden, dies zu tun, kopieren Sie den Quellcode von Ihrer Version.

1voto

Fred Willmore Punkte 4096

Ich hatte dieses Problem, aber mit der timestamps-Funktion. Sie hat einen Index auf updated_at automatisch generiert, der das 63-Zeichen-Limit überschritten hat:

def change
  create_table :toooooooooo_loooooooooooooooooooooooooooooong do |t|
    t.timestamps
  end
end

Index-Name 'index_toooooooooo_loooooooooooooooooooooooooooooong_on_updated_at' auf Tabelle 'toooooooooo_loooooooooooooooooooooooooooooong' ist zu lang; das Limit beträgt 63 Zeichen

Ich habe versucht, timestamps zu verwenden, um den Indexnamen anzugeben:

def change
  create_table :toooooooooo_loooooooooooooooooooooooooooooong do |t|
    t.timestamps index: { name: 'too_loooooooooooooooooooooooooooooong_updated_at' }
  end
end

Das versucht jedoch, den Indexnamen auf beide Felder updated_at und created_at anzuwenden:

Index-Name 'too_long_updated_at' auf Tabelle 'toooooooooo_loooooooooooooooooooooooooooooong' existiert bereits

Schließlich habe ich auf timestamps aufgegeben und einfach die Timestamps auf die lange Art erstellt:

def change
  create_table :toooooooooo_loooooooooooooooooooooooooooooong do |t|
    t.datetime :updated_at, index: { name: 'too_long_on_updated_at' }
    t.datetime :created_at, index: { name: 'too_long_on_created_at' }
  end
end

Das funktioniert, aber ich würde gerne hören, ob es mit der timestamps-Methode möglich ist!

1voto

Create_table: you_table_name do |t| t.references: Studant, Index: { name: 'name_for_studant_index' } t.references: Lehrer, Index: { name: 'name_for_teacher_index' } Ende

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X