Wie schreibt man eine Migration, um ein ActiveRecord-Modell und seine Tabelle in Rails umzubenennen?

408

Ich kann schlecht benennen und stelle fest, dass meine Rails-App bessere Namen für meine Modelle enthält.
Gibt es eine Möglichkeit, eine Migration zum Umbenennen eines Modells und der entsprechenden Tabelle zu verwenden?

Schreibgeschützt
quelle
11
Ich schlug vor, dieser Frage "ActiveRecord" hinzuzufügen, um die Übereinstimmung mit Suchmaschinen zu verbessern. Ich habe dies mit "ActiveRecord Rename Table" gesucht.
Landon Kuhn
6
Wenn Sie Migrationen verwenden, ist dieses Problem komplizierter als es scheint. Die ausgewählte Lösung besagt, dass Sie einfach zurückgehen und das Modell, den Controller usw. manuell umbenennen müssen, nachdem Sie den Tabellennamen geändert haben. Wenn Sie dies tun, schlagen alle älteren Migrationen fehl, die mit ihrem älteren Namen auf Ihr Modell verweisen. Wenn also jemand Ihr Repo klont und versucht zu laufen rake db:migrate, schlägt es fehl. Sie könnten zurückgehen und diese Namen in der Migration ändern, aber das wird chaotisch. Möglicherweise ist es besser, nur ein völlig neues Modell zu erstellen, als es umzubenennen.
Andrew
4
@andrewhannigan: Ist dein Punkt nicht umstritten, wenn jemand dein Repo klont und einfach rennt rake db:schema:load?
Istrasci
3
@istrasci: absolut. Tatsächlich rake db:migratewird davon abgeraten, eine Datenbank von Grund auf neu einzurichten, und zwar genau aufgrund der Bedenken, auf die Andrew hingewiesen hat.
Giuseppe

Antworten:

584

Hier ist ein Beispiel:

class RenameOldTableToNewTable < ActiveRecord::Migration
  def self.up
    rename_table :old_table_name, :new_table_name
  end

  def self.down
    rename_table :new_table_name, :old_table_name
  end
end

Ich musste die Modelldeklarationsdatei manuell umbenennen.

Bearbeiten:

In Rails 3.1 und 4 ActiveRecord::Migration::CommandRecordererfahren Sie , wie Sie die Migration von rename_table umkehren. Gehen Sie also folgendermaßen vor:

class RenameOldTableToNewTable < ActiveRecord::Migration
  def change
    rename_table :old_table_name, :new_table_name
  end 
end

(Sie müssen Ihre Dateien noch manuell umbenennen.)

Schreibgeschützt
quelle
6
@mathee: Ja, Sie müssen dies manuell ändern oder eine IDE verwenden, die Ruby-Refactoring durchführen und an Ihr Versionskontrollsystem übertragen kann.
Pupeno
13
Git Grep ist dein Freund. Ich benenne gerade eine Aktivität in eine Gewohnheit um: git grep -i activitist sehr aufschlussreich.
Felix Rabe
1
Sie müssen auch den Inhalt Ihres Controllers ändern, oder?
Alemur
5
Und vergessen Sie nicht Ihre Routen.rb!
Dan Herman
26
Außerdem möchten Sie als Heads-up die Pluralversion Ihres Tabellennamens im Aufruf rename_table verwenden.
Han
66

In Rails 4 musste ich nur die Def-Änderung vornehmen

def change
  rename_table :old_table_name, :new_table_name
end

Und alle meine Indizes wurden für mich gepflegt. Ich musste die Indizes nicht manuell aktualisieren, indem ich die alten entfernte und neue hinzufügte.

Und es funktioniert, wenn die Änderung auch in Bezug auf die Indizes nach oben oder unten geht.

bfcoder
quelle
47

Die anderen Antworten und Kommentare betrafen das Umbenennen von Tabellen, das Umbenennen von Dateien und das Durchsuchen Ihres Codes.

Ich möchte noch ein paar Einschränkungen hinzufügen:

Verwenden wir ein Beispiel aus der Praxis, mit dem ich heute konfrontiert war: Umbenennen eines Modells von "Händler" in "Geschäft".

  • Vergessen Sie nicht, die Namen abhängiger Tabellen und Modelle in derselben Migration zu ändern. Ich habe meine Merchant- und MerchantStat-Modelle gleichzeitig in Business und BusinessStat geändert. Andernfalls hätte ich beim Suchen und Ersetzen viel zu viel auswählen müssen.
  • Bei allen anderen Modellen, die über Fremdschlüssel von Ihrem Modell abhängen, werden die Fremdschlüsselspaltennamen der anderen Tabellen von Ihrem ursprünglichen Modellnamen abgeleitet. Daher möchten Sie auch einige rename_column-Aufrufe für diese abhängigen Modelle ausführen. Zum Beispiel musste ich die Spalte 'Merchant_id' in verschiedenen Join-Tabellen (für die Beziehung has_and_belongs_to_many) und anderen abhängigen Tabellen (für normale Beziehungen has_one und has_many) in 'business_id' umbenennen. Andernfalls hätte ich Spalten wie 'business_stat.merchant_id' erhalten, die auf 'business.id' verweisen. Hier ist eine gute Antwort zum Umbenennen von Spalten.
  • Denken Sie beim Greppen daran, nach Singular-, Plural-, Groß-, Klein- und sogar Großbuchstaben (die in Kommentaren vorkommen können) Ihrer Zeichenfolgen zu suchen.
  • Es ist am besten, zuerst nach Pluralversionen und dann nach Singular zu suchen. Auf diese Weise können Sie, wenn Sie einen unregelmäßigen Plural haben - wie in meinem Beispiel für Händler :: Unternehmen - alle unregelmäßigen Pluralformen korrigieren. Andernfalls könnten Sie beispielsweise "Unternehmen" (3 s) als Zwischenzustand haben, was zu noch mehr Suchen und Ersetzen führt.
  • Ersetzen Sie nicht jedes Vorkommen blind. Wenn Ihre Modellnamen mit allgemeinen Programmierbegriffen, mit Werten in anderen Modellen oder mit Textinhalten in Ihren Ansichten kollidieren, sind Sie möglicherweise zu eifrig. In meinem Beispiel wollte ich meinen Modellnamen in "Business" ändern, sie aber im Inhalt meiner Benutzeroberfläche immer noch als "Händler" bezeichnen. Ich hatte auch eine Händlerrolle für meine Benutzer in CanCan - es war die Verwechslung zwischen der Händlerrolle und dem Händlermodell, die mich veranlasste, das Modell überhaupt umzubenennen.
armchairdj
quelle
26

Sie müssen auch Ihre Indizes ersetzen:

class RenameOldTableToNewTable< ActiveRecord:Migration
  def self.up
    remove_index :old_table_name, :column_name
    rename_table :old_table_name, :new_table_name
    add_index :new_table_name, :column_name
  end 

  def self.down
    remove_index :new_table_name, :column_name
    rename_table :new_table_name, :old_table_name
    add_index :old_table_name, :column_name
  end
end

Und benennen Sie Ihre Dateien usw. manuell um, wie in anderen Antworten hier beschrieben.

Siehe: http://api.rubyonrails.org/classes/ActiveRecord/Migration.html

Stellen Sie sicher, dass Sie nach dem Schreiben dieser Migration einen Rollback und einen Rollback durchführen können. Es kann schwierig werden, wenn Sie etwas falsch machen und bei einer Migration stecken bleiben, die versucht, etwas zu bewirken, das nicht mehr existiert. Am besten werfen Sie die gesamte Datenbank in den Papierkorb und starten Sie erneut, wenn Sie kein Rollback durchführen können. Seien Sie sich also bewusst, dass Sie möglicherweise etwas sichern müssen.

Außerdem: Überprüfen Sie schema_db auf relevante Spaltennamen in anderen Tabellen, die durch ein has_ ​​odereins_to oder etwas definiert sind. Sie müssen diese wahrscheinlich auch bearbeiten.

Und schließlich wäre es verrückt, dies ohne eine Regressionstestsuite zu tun.

Rimian
quelle
11
Bei Rails 4.0.0.beta1-Migrationen ist es nicht erforderlich, die Indizes manuell zu aktualisieren. AR aktualisiert es von selbst.
Freemanoid
1

Sie können diesen Befehl ausführen: Rails g Migration Rename_ {alter_Tabellenname} nach {neuer_Tabellenname}

Nachdem Sie die Datei bearbeitet und diesen Code in die Methodenänderung eingefügt haben

Umbenennungstabelle: {alter_Tabellenname} ,: {neuer_Tabellenname}

Mouhamadou Bamba Mboup
quelle