Rails-Migrationen: Existenz prüfen und weitermachen?

80

Ich habe bei meinen Migrationen so etwas gemacht:

add_column :statuses, :hold_reason, :string rescue puts "column already added"

Es stellt sich jedoch heraus, dass dies zwar für SQLite funktioniert, für PostgreSQL jedoch nicht . Es scheint, als ob die add_column explodiert, selbst wenn die Ausnahme abgefangen wird, die Transaktion tot ist und die Migration keine zusätzliche Arbeit leisten kann.

Gibt es nicht DB-spezifische Möglichkeiten, um zu überprüfen, ob bereits eine Spalte oder Tabelle vorhanden ist? Wenn das nicht gelingt, gibt es eine Möglichkeit, meinen Rettungsblock wirklich zum Laufen zu bringen?

Dan Rosenstark
quelle
Es muss erwähnt werden, dass die bedingte Migration zu Problemen mit dem Rollback führt, da im Rollback-Stadium nicht bekannt ist, welche Bedingungen während der Vorwärtsmigration
herrschten
Machen Sie nur den nicht optionalen Teil beim Rollback
Dan Rosenstark

Antworten:

175

Ab Rails 3.0 und höher können Sie column_exists?überprüfen, ob eine Spalte vorhanden ist.

unless column_exists? :statuses, :hold_reason
  add_column :statuses, :hold_reason, :string
end

Es gibt auch eine table_exists?Funktion, die bis zu Rails 2.1 zurückreicht.

Tobias Cohen
quelle
Wird es als bewährte Methode angesehen, vor dem Hinzufügen / Erstellen zu überprüfen, ob eine Spalte / Tabelle vorhanden ist? (Ich weiß natürlich, dass es auf das Problem in den Händen
ankommt
4
Funktioniert dies mit Rollbacks, wenn ich es in der Änderungsmethode definiere?
Dardub
1
Ja, Rollback wäre ein Problem ... wir sind uns nicht sicher, ob wir die Spalte entfernen sollen oder nicht ... da wir den vorherigen Status nicht aufzeichnen.
Songyy
8

Oder noch kürzer

add_column :statuses, :hold_reason, :string unless column_exists? :statuses, :hold_reason
SG 86
quelle
Dies wäre ein Kommentar zur anderen Antwort, keine Antwort. Vielen Dank.
Dan Rosenstark
4

Für Rails 2.X können Sie das Vorhandensein von Spalten wie folgt überprüfen:

columns("[table-name]").index {|col| col.name == "[column-name]"}

Wenn nil zurückgegeben wird, ist keine solche Spalte vorhanden. Wenn eine Fixnummer zurückgegeben wird, ist die Spalte vorhanden. Natürlich können Sie selektivere Parameter zwischen die setzen, {...}wenn Sie eine Spalte nicht nur anhand ihres Namens identifizieren möchten, zum Beispiel:

{ |col| col.name == "foo" and col.sql_type == "tinyint(1)" and col.primary == nil }

(Diese Antwort wurde zuerst veröffentlicht unter Wie schreibe ich bedingte Migrationen in Schienen? )

JellicleCat
quelle
0

add_column :statuses, :hold_reason, :string unless Status.column_names.include?("hold_reason")

Denis Neverov
quelle