Fügen Sie einer Spalte durch eine Migration einen Standardwert hinzu

276

Wie füge ich einer Spalte, die bereits während einer Migration vorhanden ist, einen Standardwert hinzu?

Die gesamte Dokumentation, die ich finden kann, zeigt Ihnen, wie es geht, wenn die Spalte noch nicht vorhanden ist, in diesem Fall jedoch.

Jon
quelle

Antworten:

352

So sollten Sie es machen:

change_column :users, :admin, :boolean, :default => false

Einige Datenbanken, wie z. B. PostgreSQL, aktualisieren das Feld für zuvor erstellte Zeilen jedoch nicht. Stellen Sie daher sicher, dass Sie das Feld auch bei der Migration manuell aktualisieren.

Maurício Linhares
quelle
14
Wenn Sie reversible Migrationen benötigen, fügen Sie diese in einen upBlock anstatt in einen Block ein change. Sie können den downBlock leer lassen. Die Tabelle wird nicht in den ursprünglichen Zustand zurückgesetzt, aber die Migration kann zurückgesetzt werden.
IAmNaN
1
Wird dies die Daten intakt halten?
Marco Prins
2
Auf PostgreSQL weiß ich nicht, was auf anderen Datenbanken passieren wird.
Maurício Linhares
1
Was meinen Sie mit "Stellen Sie sicher, dass Sie das Feld bei der Migration manuell aktualisieren"? Wie macht man das?
David Argyle Thacker
7
Ich habe es unter PostgreSQL versucht und zuvor erstellte Felder aktualisiert.
Aboozar Rajabi
190
change_column_default :employees, :foreign, false
Gazza
quelle
1
@DenisLins Ich habe Ihnen zugestimmt, also habe ich einige Nachforschungen angestellt, um herauszufinden, warum dies möglicherweise nicht der Fall ist, und es stellt sich heraus, dass ein bestimmter Datenbankadapter dies möglicherweise nicht unterstützt, da es auf dieser Ebene implementiert ist. Die akzeptierte Antwort ist immer noch die sicherste Wette, bis sie im abstrakten Modell implementiert ist. apidock.com/rails/ActiveRecord/ConnectionAdapters/…
natchiketa
5
Außerdem müssen Sie ein angeben from:und to:wenn Sie möchten, dass es reversibel ist :)
radubogdan
5
Verwenden fromund towurde in Rails 5+ in diesem Commit hinzugefügt: github.com/rails/rails/pull/20018/files
Joshua Pinter
113

Verwenden Sie für Rails 4+change_column_default

def change
  change_column_default :table, :column, value
end
csi
quelle
1
Dies ist besonders dann von Vorteil, wenn Sie eine Migration haben, bei der eine Spalte hinzugefügt und Standardeinstellungen für vorhandene Datensätze festgelegt werden. Zum Beispiel: def change `add_column: foos ,: name, default:" etwas für vorhandene Werte "` `change_column_default: foos ,: name, default:" "`end
user1491929
2
Diese Migration hat ein seltsames Verhalten. In Ihrem Beispiel ist es irreversibel. edgeguides.rubyonrails.org/active_record_migrations.html empfehlen, es folgendermaßen zu verwenden: change_column_default :products, :approved, from: true, to: false- aber es funktioniert auch nicht.
Ilya Krigouzov
Kann ich das nicht rückgängig machen?
aldrien.h
Normalerweise ja, für fast jede "Änderungs" -Klausel, da alle vorherigen Zustände normalerweise explizit sind, z. B. das Vorhandensein einer Spalte, ihr Typ usw. Die Änderung kann genau dann zurückgesetzt werden, wenn sie dort angezeigt wird zuvor gültiger expliziter Standard. Da die Standardeinstellungen häufig nicht definiert sind, liegt möglicherweise ein Problem vor.
Elindor
48

Mit def changebedeutet, dass Sie Migrationen schreiben sollten, die reversibel sind. Und change_columnist nicht umkehrbar. Sie können nach oben gehen, aber Sie können nicht nach unten gehen, da dies change_columnirreversibel ist.

Stattdessen, obwohl es ein paar zusätzliche Zeilen sein können, sollten Sie verwenden def upunddef down

Wenn Sie also eine Spalte ohne Standardwert haben, sollten Sie dies tun, um einen Standardwert hinzuzufügen.

def up
  change_column :users, :admin, :boolean, default: false
end

def down
  change_column :users, :admin, :boolean, default: nil
end

Oder wenn Sie den Standardwert für eine vorhandene Spalte ändern möchten.

def up
  change_column :users, :admin, :boolean, default: false
end

def down
  change_column :users, :admin, :boolean, default: true
end
bfcoder
quelle
37

** Schienen 4.X + **

Ab Rails 4 können Sie keine Migration generieren, um einer Tabelle mit einem Standardwert eine Spalte hinzuzufügen. Mit den folgenden Schritten wird einer vorhandenen Tabelle mit dem Standardwert true oder false eine neue Spalte hinzugefügt.

1. Führen Sie die Migration von der Befehlszeile aus, um die neue Spalte hinzuzufügen

$ rails generate migration add_columnname_to_tablename columnname:boolean

Mit dem obigen Befehl wird eine neue Spalte in Ihre Tabelle eingefügt.

2. Setzen Sie den neuen Spaltenwert auf TRUE / FALSE, indem Sie die neu erstellte Migrationsdatei bearbeiten.

class AddColumnnameToTablename < ActiveRecord::Migration
  def change
    add_column :table_name, :column_name, :boolean, default: false
  end
end

**3. Führen Sie den folgenden Befehl in Terminal ** aus, um die Änderungen in Ihrer Anwendungsdatenbanktabelle vorzunehmen

$ rake db:migrate
Praveen George
quelle
Wie unterscheidet sich das von den Schienen 3+ oder 2+?
Ruby Racer
2
Weiß jemand, ob dies in Rails 5 aufgenommen wurde?
Sambecker
9

Ausführen:

rails generate migration add_column_to_table column:boolean

Diese Migration wird generiert:

class AddColumnToTable < ActiveRecord::Migration
  def change
    add_column :table, :column, :boolean
  end
end

Stellen Sie den Standardwert ein, indem Sie Folgendes hinzufügen: Standard => 1

add_column: table ,: column ,: boolean ,: default => 1

Lauf:

Rechen db: migrieren

Axeltaglia
quelle
2
Jetzt ist der Standardwert von 1 nicht gerade ein Boolescher Wert;) Außerdem fügt diese Exampe eine neue Spalte hinzu, anstatt die vorhandene Spalte zu ändern, was das OP erreichen wollte
Radiospiel
@ Radiospiel Eigentlich ist 1 auch ein Boolescher
Wert
Sie müssen auch einen Datensatz in der Fremdschlüsseltabelle mit der ID 1 erstellen, damit dies funktioniert, um das zu vermeiden Key is not present in table error.
Versprich Preston den
-50

Folgendes können Sie tun:

class Profile < ActiveRecord::Base
  before_save :set_default_val

  def set_default_val
    self.send_updates = 'val' unless self.send_updates
  end
end

EDIT: ... aber anscheinend ist das ein Rookie-Fehler!

rookieRailer
quelle
Es ist besser, wenn Sie die Standardeinstellung im Schema vs alsbefore_save
rigelstpierre
6
Was für ein schrecklicher Vorschlag
svelandiag
stimmte zu, es ist wirklich schrecklich
Houcheng
2
autsch, du hast viel Wärme dafür, etwas auf Modellebene anstatt auf Datenbankebene zu tun. -38 ist eine legendäre Partitur.
Nurettin
1
Was für ein Anfängerfehler ... ;-)
Webaholik