Schienen: Hinzufügen eines Index nach dem Hinzufügen einer Spalte


119

Angenommen, ich habe eine Tabelle tablein einer Rails-App erstellt. Einige Zeit später füge ich eine Spalte hinzu, die ausgeführt wird:

rails generate migration AddUser_idColumnToTable user_id:string. 

Dann wird mir klar, dass ich user_idals Index hinzufügen muss . Ich weiß über die add_indexMethode Bescheid , aber wo soll diese Methode aufgerufen werden? Soll ich eine Migration durchführen (wenn ja, welche?) Und diese Methode dann von Hand hinzufügen?

Antworten:


235

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

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

4
Also laufe ich einfach in meiner Konsole: Rails generieren Migration AddIndexToTable?
user1611830

3
Ja, das können Sie tun, aber Sie müssen diese Migration anschließend bearbeiten, um den obigen Code wiederzugeben.
Jaap Haagmans

Soll: Tabelle Plural sein?
Grab

1
@ Grab Ich habe das Beispiel aus der ursprünglichen Frage verwendet. :tableist der eigentliche Name der Tabelle, so im Fall einer usersTabelle, dann würden Sie ersetzen :usersfür :table.
Jaap Haagmans

65

Wenn Sie eine erstellen müssen, user_idist es eine vernünftige Annahme, dass Sie auf eine Benutzertabelle verweisen. In diesem Fall muss die Migration sein:

rails generate migration AddUserRefToProducts user:references

Dieser Befehl generiert die folgende Migration:

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

Nach dem Ausführen werden rake db:migratesowohl eine user_idSpalte als auch ein Index zur productsTabelle hinzugefügt .

Wenn Sie einer vorhandenen Spalte, z. B. nameeiner userTabelle, nur einen Index hinzufügen müssen , kann die folgende Technik hilfreich sein:

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

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

add_columnZeile löschen und Migration ausführen.

In dem beschriebenen Fall könnten Sie einen rails generate migration AddIndexIdToTable index_id:integer:indexBefehl ausgegeben und dann die add_columnZeile aus der generierten Migration gelöscht haben . Ich würde jedoch eher empfehlen, die anfängliche Migration rückgängig zu machen und stattdessen eine Referenz hinzuzufügen:

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

Danke Vadym für die vollständige Antwort. Eine letzte Frage: Warum empfehlen Sie, die anfängliche Migration rückgängig zu machen? Gibt es Leistungsprobleme im Zusammenhang mit dem späteren Hinzufügen eines Index?
Flavio Wuensche

2
Zu @fwuensche: Es gibt keine Leistungseinbußen für das spätere Hinzufügen eines Index. Die Domänenlogik wird jedoch weniger klar sein. Wenn Sie sich beispielsweise dazu entschließen, die Assoziation später zu brechen / zu abstrahieren / usw., müssen Sie sich mit zwei getrennten Migrationen befassen, die eigentlich eine einzige sein sollten ...
Vadym Tyemirov

5
WARNUNG: Beachten Sie, dass index: true nur bei einer Migration von create_table funktioniert. Die Migration wird ausgeführt, es wird jedoch kein Index erstellt. Siehe makandracards.com/makandra/…
rmcsharry

9

Fügen Sie in der generierten Migration nach dem Erstellen der Spalte Folgendes hinzu (Beispiel)

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

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

5

Für Referenzen können Sie anrufen

rails generate migration AddUserIdColumnToTable user:references

Wenn Sie in Zukunft einen allgemeinen Index hinzufügen müssen, können Sie diesen 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 :tables, :ordination_number, unique: true
  end
end

0

Sie können dies verwenden. Denken Sie nur, Job ist der Name des Modells, zu dem Sie den Index cader_id hinzufügen :

class AddCaderIdToJob < ActiveRecord::Migration[5.2]
  def change
    change_table :jobs do |t|
      t.integer :cader_id
      t.index :cader_id
    end
  end
end
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.