wake-up-neo.net

Fügen Sie einer vorhandenen Tabelle Zeitstempel hinzu

Ich muss einer vorhandenen Tabelle Zeitstempel (created_at updated_at) hinzufügen. Ich habe den folgenden Code ausprobiert, aber er hat nicht funktioniert. Ich habe auch andere Lösungen ausprobiert, die ich online gefunden habe, aber sie funktionieren auch nicht.

class AddTimestampsToUser < ActiveRecord::Migration
    def change_table
      add_timestamps(:users)
    end
end

Wie kann ich es tun?

150
leonel

Der Zeitstempel-Helfer ist nur im create_table-Block verfügbar. Sie können diese Spalten hinzufügen, indem Sie die Spaltentypen manuell angeben: 

class AddTimestampsToUser < ActiveRecord::Migration
  def change_table
    add_column :users, :created_at, :datetime, null: false
    add_column :users, :updated_at, :datetime, null: false
  end
end

Dies hat zwar nicht die gleiche knappe Syntax wie die oben angegebene add_timestamps-Methode, aber Rails behandelt diese Spalten immer noch als Zeitstempelpalten und aktualisiert die Werte normal.

189
Ben Simpson

Migrationen sind nur zwei Klassenmethoden (oder Instanzmethoden in 3.1): up und down (und manchmal auch eine change-Instanzmethode in 3.1). Sie möchten, dass Ihre Änderungen in die up-Methode übernommen werden:

class AddTimestampsToUser < ActiveRecord::Migration
  def self.up # Or `def up` in 3.1
    change_table :users do |t|
      t.timestamps
    end
  end
  def self.down # Or `def down` in 3.1
    remove_column :users, :created_at
    remove_column :users, :updated_at
  end
end

Wenn Sie in 3.1 sind, können Sie auch change verwenden (danke Dave):

class AddTimestampsToUser < ActiveRecord::Migration
  def change
    change_table(:users) { |t| t.timestamps }
  end
end

Möglicherweise sind Sie def change, def change_table und change_table verwirrend.

Weitere Informationen finden Sie im migration guide .

85
mu is too short

Ihr ursprünglicher Code steht ganz rechts, Sie müssen nur einen anderen Methodennamen verwenden. Wenn Sie Rails 3.1 oder höher verwenden, müssen Sie anstelle von change_table eine change-Methode definieren:

class AddTimestampsToUser < ActiveRecord::Migration
  def change
    add_timestamps(:users)
  end
end

Wenn Sie eine ältere Version verwenden, müssen Sie statt change_tableup- und down-Methoden definieren:

class AddTimestampsToUser < ActiveRecord::Migration
  def up
    add_timestamps(:users)
  end

  def down
    remove_timestamps(:users)
  end
end
68
georgebrock
class AddTimestampsToUser < ActiveRecord::Migration
  def change
    change_table :users do |t|
      t.timestamps
    end
  end
end

Verfügbare Transformationen sind

change_table :table do |t|
  t.column
  t.index
  t.timestamps
  t.change
  t.change_default
  t.rename
  t.references
  t.belongs_to
  t.string
  t.text
  t.integer
  t.float
  t.decimal
  t.datetime
  t.timestamp
  t.time
  t.date
  t.binary
  t.boolean
  t.remove
  t.remove_references
  t.remove_belongs_to
  t.remove_index
  t.remove_timestamps
end

http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/Table.html

37
Pradeep Sanjaya

Die Antwort von @ user1899434 hat sich auf die Tatsache bezogen, dass eine "vorhandene" Tabelle hier eine Tabelle mit bereits vorhandenen Datensätzen bedeuten kann, Datensätze, die möglicherweise nicht gelöscht werden sollen. Wenn Sie also Zeitstempel mit null: false hinzufügen (Standardeinstellung und häufig erwünscht), sind alle vorhandenen Datensätze ungültig.

Ich denke jedoch, dass die Antwort durch die Kombination der beiden Schritte in einer Migration und die Verwendung der semantischeren Methode add_timestamps verbessert werden kann:

def change
  add_timestamps :projects, default: Time.zone.now
  change_column_default :projects, :created_at, nil
  change_column_default :projects, :updated_at, nil
end

Sie können DateTime.now durch einen anderen Zeitstempel ersetzen, z. B. wenn Sie möchten, dass bereits vorhandene Datensätze zu Beginn erstellt/aktualisiert werden.

36
Nick Davies
def change
  add_timestamps :table_name
end
8
Ian Vaughan

Nick Davies Antwort ist die umfassendste in Bezug auf das Hinzufügen von Zeitstempelspalten zu einer Tabelle mit vorhandenen Daten. Der einzige Nachteil ist, dass es ActiveRecord::IrreversibleMigration auf einen db:rollback erhöht.

Es sollte so modifiziert werden, dass es in beide Richtungen funktioniert:

def change
  add_timestamps :campaigns, default: DateTime.now
  change_column_default :campaigns, :created_at, from: DateTime.now, to: nil
  change_column_default :campaigns, :updated_at, from: DateTime.now, to: nil
end
4
lightyrs

Ich habe eine einfache Funktion erstellt, die Sie aufrufen können, um zu each table (sofern Sie eine vorhandene Datenbank haben) die created_at und updated_at Felder hinzuzufügen:

  # add created_at and updated_at to each table found.
  def add_datetime
    tables = ActiveRecord::Base.connection.tables
    tables.each do |t|
      ActiveRecord::Base.connection.add_timestamps t  
    end    
  end
2
Roger

add_timestamps (tabellenname, options = {}) public

Fügt Zeitstempel (created_at und updated_at) zu Tabellenname hinzu. Zusätzliche Optionen (wie null: false) werden an #add_column weitergeleitet.

class AddTimestampsToUsers < ActiveRecord::Migration
  def change
    add_timestamps(:users, null: false)
  end
end
2
almawhoob

Viele Antworten hier, aber ich werde auch meine posten, weil keine der vorherigen wirklich für mich gearbeitet hat :)

Wie einige angemerkt haben, fügt #add_timestamps leider die Einschränkung null: false hinzu, die dazu führt, dass alte Zeilen ungültig werden, da diese Werte nicht ausgefüllt sind. Die meisten Antworten hier deuten darauf hin, dass wir einen Standardwert (Time.zone.now) festgelegt haben, 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:

class AddTimestampsToUser < ActiveRecord::Migration
  def change_table
    add_column :projects, :created_at, :datetime
    add_column :projects, :updated_at, :datetime
  end
end

Nein null: false, keine weiteren Einschränkungen. Alte Zeilen behalten ihre Gültigkeit mit created_at als NULL und update_at als NULL (bis eine Aktualisierung der Zeile durchgeführt wird). In neuen Zeilen sind created_at und updated_at wie erwartet ausgefüllt.

1
Kostis

Die Antworten davor scheinen richtig zu sein, aber ich hatte Probleme, wenn meine Tabelle bereits Einträge hat.

Ich würde 'ERROR: Spalte created_at enthält null Werte' erhalten.

Um das zu beheben, habe ich verwendet:

def up
  add_column :projects, :created_at, :datetime, default: nil, null: false
  add_column :projects, :updated_at, :datetime, default: nil, null: false
end

Ich habe dann mit gem migration_data die Zeit für aktuelle Projekte zur Migration hinzugefügt, wie:

def data
  Project.update_all created_at: Time.now
end

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.

1
dbrody

Es ist change, nicht change_table für Rails 4.2:

class AddTimestampsToUsers < ActiveRecord::Migration
  def change
    add_timestamps(:users)
  end
end
0
Igor T.

sie wissen nicht genau, wann genau dies eingeführt wurde, aber in Rails 5.2.1 können Sie Folgendes tun:

class AddTimestampsToMyTable < ActiveRecord::Migration[5.2]
  def change
    add_timestamps :my_table
  end
end

weitere Informationen finden Sie unter " mit der Änderungsmethode " in den aktiven Datensatzmigrationsdokumenten.

0
Reef Loretto

Für diejenigen, die Rails nicht verwenden, aber Activerecord verwenden, fügt das Folgende auch eine Spalte zu einem vorhandenen Modell hinzu. Beispiel ist ein ganzzahliges Feld.

ActiveRecord::Schema.define do
  change_table 'MYTABLE' do |table|
    add_column(:mytable, :my_field_name, :integer)
  end
end
0
peter