2013-04-08 1 views
65

Angenommen, ich erstellte eine Tabelle table in einer Rails App. Einige Zeit später, füge ich eine Säule läuft:Schienen: Hinzufügen eines Index nach dem Hinzufügen der Spalte

rails generate migration AddUser_idColumnToTable user_id:string. 

Dann merke ich, ich brauche user_id als Index hinzuzufügen. Ich kenne die add_index Methode, aber wo sollte diese Methode aufgerufen werden? Soll ich eine Migration durchführen (wenn ja, welche?) Und dann diese Methode manuell hinzufügen?

Antwort

147

Sie eine weitere Migration ausführen können, nur für den Index:

class AddIndexToTable < ActiveRecord::Migration 
    def change 
    add_index :table, :user_id 
    end 
end 
+1

So renne ich einfach in meiner Konsole: Schienen erzeugen Migration AddIndexToTable? – user1611830

+1

Ja, Sie können das tun, aber Sie müssen diese Migration anschließend bearbeiten, um den obigen Code widerzuspiegeln. –

+0

ja sicher, danke! – user1611830

7

in der generierten Migration hinzufügen, nachdem die Spalte die folgenden (Beispiel)

add_index :photographers, :email, :unique => true 
+0

du meinst so etwas wie: def self.up add_column ... end add_index ...? – user1611830

45

Wenn Sie eine user_id erstellen müssen die Schaffung dann wäre es eine vernünftige Annahme, dass Sie eine Benutzertabelle referenzieren. In diesem Fall wird die Migration sein:

rails generate migration AddUserRefToProducts user:references 

Dieser Befehl die folgende Migration generieren:

class AddUserRefToProducts < ActiveRecord::Migration 
    def change 
    add_reference :user, :product, index: true 
    end 
end 

Nach rake db:migrate läuft sowohl eine Spalte und ein Index wird product Tabelle hinzugefügt werden.

Falls Sie nur einen Index zu einer vorhandenen Spalte hinzufügen müssen, z. name eine user Tabelle, kann die folgende Technik hilfreich sein:

rails generate migration AddIndexToUsers name:string:index die folgende Migration generieren:

class AddIndexToUsers < ActiveRecord::Migration 
    def change 
    add_column :users, :name, :string 
    add_index :users, :name 
    end 
end 

add_column Zeilen löschen und die Migration ausführen.

In dem beschriebenen Fall hätten Sie den Befehl rails generate migration AddIndexIdToTable index_id:integer:index ausgeben und dann die Zeile add_column aus der generierten Migration löschen können. Aber ich würde eher empfohlen, die erste Migration rückgängig zu machen, und fügen Sie Referenz statt:

rails generate migration RemoveUserIdFromProducts user_id:integer 
rails generate migration AddUserRefToProducts user:references 
+0

Danke Vadym für die vollständige Antwort. Eine letzte Frage: Warum sollten Sie die anfängliche Migration rückgängig machen? Gibt es ein Leistungsproblem im Zusammenhang mit dem späteren Hinzufügen eines Index? –

+2

Um @fwuensche: Es gibt keine Leistungseinbußen für das Hinzufügen von Index später. Die Domänenlogik wird jedoch weniger klar sein. Z.B. Für den Fall, dass Sie sich dazu entschließen, die Verknüpfung später zu lösen/abstrakt/etc, müssen Sie sich mit zwei separaten Migrationen befassen, die wirklich eine einzige sein sollten ... –

+2

WARNUNG: Beachten Sie, dass index: true nur in a funktioniert create_table Migration. Die Migration wird ausgeführt, aber es wird kein Index erstellt. Siehe https://makandracards.com/makandra/32353-psa-index-true-in-rails-migrations-does-not-works-as-you-d-expect – rmcsharry

1

Für Referenzen können Sie anrufen

rails generate migration AddUserIdColumnToTable user:references 

Wenn Sie in Zukunft einen allgemeinen Index hinzufügen möchten, können Sie diese starten

rails g migration AddOrdinationNumberToTable ordination_number:integer:index 

Code generieren:

class AddOrdinationNumberToTable < ActiveRecord::Migration 
    def change 
    add_column :tables, :ordination_number, :integer 
    add_index :dt_json_structs, :ordination_number, unique: true 
    end 
end