Ich muss einer vorhandenen Tabelle Zeitstempel ( created_at
& updated_at
) hinzufügen . Ich habe den folgenden Code ausprobiert, aber er hat nicht funktioniert.
class AddTimestampsToUser < ActiveRecord::Migration
def change_table
add_timestamps(:users)
end
end
rails g migration AddTimestampsToUser created_at:datetime updated_at:datetime
- eine Verknüpfung zum Generieren der obigen Migration.PG::NotNullViolation: ERROR: column "created_at" contains null value
da meine Tabelle bereits Daten enthält, die nicht gegen die Null-Einschränkung verstoßen. Gibt es eine bessere Möglichkeit, dies zu tun, als zuerst die Nicht-Null-Kontraint zu entfernen und sie später hinzuzufügen?add_column :users, :updated_at, :datetime, null: false, default: Time.zone.now
.Time.zone.now
ist nur ein Beispiel, Sie sollten jeden Wert verwenden, der für Ihre Logik sinnvoll ist.Migrationen sind nur zwei Klassenmethoden (oder Instanzmethoden in 3.1):
up
unddown
(und manchmal einechange
Instanzmethode in 3.1). Sie möchten, dass Ihre Änderungen in dieup
Methode übernommen werden:Wenn Sie in 3.1 sind, können Sie auch verwenden
change
(danke Dave):Vielleicht sind verwirrend Sie
def change
,def change_table
undchange_table
.Weitere Informationen finden Sie im Migrationshandbuch .
quelle
change
jetzt die Methode, obwohl in diesem Fall nicht das Problem :)change
ist eine Erwähnung wert, also werde ich das auch hinzufügen.Ihr ursprünglicher Code befindet sich ganz in der Nähe von rechts. Sie müssen lediglich einen anderen Methodennamen verwenden. Wenn Sie Rails 3.1 oder höher verwenden, müssen Sie eine
change
Methode definieren , anstattchange_table
:Wenn Sie eine ältere Version verwenden, müssen Sie
up
unddown
Methoden definieren , anstattchange_table
:quelle
Die Antwort von @ user1899434 hat die Tatsache aufgegriffen, dass eine "vorhandene" Tabelle hier eine Tabelle mit bereits darin enthaltenen Datensätzen bedeuten kann, Datensätze, die Sie möglicherweise nicht löschen möchten. Wenn Sie also Zeitstempel mit null: false hinzufügen, was die Standardeinstellung ist und häufig wünschenswert ist, sind alle vorhandenen Datensätze ungültig.
Ich denke jedoch, dass die Antwort verbessert werden kann, indem die beiden Schritte zu einer Migration kombiniert werden und die semantischere Methode add_timestamps verwendet wird:
Sie können einen anderen Zeitstempel ersetzen, z
DateTime.now
. B. wenn bereits vorhandene Datensätze zu Beginn der Zeit erstellt / aktualisiert werden sollen.quelle
Time.zone.now
sollte verwendet werden, wenn unser Code der richtigen Zeitzone entsprechen soll.Time.zone.now
der die beim Ausführen der Migration erstellte Zeitinstanz zurückgegeben wird und nur diese Zeit als Standard verwendet wird. Neue Objekte erhalten keine neue Zeitinstanz.Verfügbare Transformationen sind
http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/Table.html
quelle
Die Antwort von Nick Davies ist die vollständigste, wenn es darum geht, einer Tabelle mit vorhandenen Daten Zeitstempelspalten hinzuzufügen. Sein einziger Nachteil ist , dass es anheben wird
ActiveRecord::IrreversibleMigration
auf einemdb:rollback
.Es sollte so modifiziert werden, dass es in beide Richtungen funktioniert:
quelle
change_column_default
es wird nicht unterstütztfrom
undto
in dieser Version?), Aber ich nahm diese Idee und erstellteup/down
Methoden anstelle einer einzelnenchange
Methode und es funktionierte wie ein Zauber!quelle
Ich bin mir nicht sicher, wann genau dies eingeführt wurde, aber in Rails 5.2.1 können Sie dies tun:
Weitere Informationen finden Sie unter " Verwenden der Änderungsmethode " in den Dokumenten zur aktiven Datensatzmigration.
quelle
, null: true
nach dem:my_table
Ich habe eine einfache Funktion erstellt, die Sie aufrufen können, um jeder Tabelle (vorausgesetzt, Sie haben eine vorhandene Datenbank) die Felder created_at und updated_at hinzuzufügen :
quelle
Fügt dem Tabellennamen Zeitstempelspalten (created_at und updated_at) hinzu. Zusätzliche Optionen (wie null: false) werden an #add_column weitergeleitet.
quelle
Die Antworten zuvor scheinen richtig zu sein, aber ich hatte Probleme, wenn meine Tabelle bereits Einträge enthält.
Ich würde 'ERROR: Spalte
created_at
enthältnull
Werte' erhalten.Um das Problem zu beheben, habe ich Folgendes verwendet:
Ich habe dann das Gem Migration_Data verwendet , um die Zeit für aktuelle Projekte für die Migration hinzuzufügen, z.
Dann werden alle nach dieser Migration erstellten Projekte korrekt aktualisiert. Stellen Sie sicher, dass auch der Server neu gestartet wird, damit Rails
ActiveRecord
die Zeitstempel im Datensatz verfolgt.quelle
Viele Antworten hier, aber ich werde auch meine posten, weil keine der vorherigen wirklich für mich funktioniert hat :)
Wie einige angemerkt haben, wird
#add_timestamps
leider dienull: false
Einschränkung hinzugefügt, die dazu führt, dass alte Zeilen ungültig werden, da diese Werte nicht ausgefüllt sind. Die meisten Antworten hier legen nahe, dass wir einen Standardwert (Time.zone.now
) festlegen , aber ich würde das nicht gerne tun, da diese Standardzeitstempel für alte Daten nicht korrekt sind. Ich sehe den Wert nicht darin, der Tabelle falsche Daten hinzuzufügen.Meine Migration war also einfach:
Nein
null: false
, keine weiteren Einschränkungen. Alte Zeilen bleiben mitcreated_at
asNULL
undupdate_at
as weiterhin gültigNULL
(bis eine Aktualisierung der Zeile durchgeführt wird). Neue Zeilen habencreated_at
undupdated_at
wie erwartet bevölkert.quelle
Das Problem mit den meisten Antworten hier ist, dass, wenn Sie standardmäßig
Time.zone.now
alle Datensätze verwenden, die Zeit, zu der die Migration ausgeführt wurde, als Standardzeit angegeben wird, was wahrscheinlich nicht das ist, was Sie möchten. In Schienen 5 können Sie stattdessen verwendennow()
. Dadurch werden die Zeitstempel für vorhandene Datensätze als Zeitpunkt der Ausführung der Migration und als Startzeit der Festschreibungstransaktion für neu eingefügte Datensätze festgelegt.class AddTimestampsToUsers < ActiveRecord::Migration def change add_timestamps :users, default: -> { 'now()' }, null: false end end
quelle
Die Verwendung
Time.current
ist ein guter Stil https://github.com/rubocop-hq/rails-style-guide#timenowoder
quelle
Dies ist einfach, um einen Zeitstempel in eine vorhandene Tabelle einzufügen.
quelle
Für diejenigen, die keine Rails verwenden, aber activerecord verwenden, wird im Folgenden auch eine Spalte zu einem vorhandenen Modell hinzugefügt. Ein Beispiel ist ein ganzzahliges Feld.
quelle
Es ist
change
nichtchange_table
für Rails 4.2:quelle
Dies scheint eine saubere Lösung in Rails 5.0.7 zu sein (die Methode change_column_null wurde entdeckt):
quelle
Ich bin auf Rails 5.0 und keine dieser Optionen hat funktioniert.
Das einzige, was funktionierte, war die Verwendung des Typs: Zeitstempel und nicht: Datum / Uhrzeit
quelle
Ich persönlich habe Folgendes verwendet und alle vorherigen Datensätze mit der aktuellen Uhrzeit / dem aktuellen Datum aktualisiert:
quelle
Ich bin auf Rails 5 auf dasselbe Problem gestoßen, als ich versucht habe, es zu verwenden
Ich konnte die Zeitstempelspalten manuell wie folgt hinzufügen:
quelle