181 votes

Ajouter des horodatages à une table existante

J'ai besoin d'ajouter des horodatages ( created_at & updated_at ) à une table existante. J'ai essayé le code suivant mais cela n'a pas fonctionné.

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

226voto

Ben Simpson Points 1797

L'aide timestamp n'est disponible que dans le module create_table bloc. Vous pouvez ajouter ces colonnes en spécifiant les types de colonnes manuellement :

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

Bien qu'elle n'ait pas la même syntaxe laconique que l'option add_timestamps que vous avez spécifié ci-dessus, Rails traitera toujours ces colonnes comme des colonnes d'horodatage, et mettra à jour les valeurs normalement.

10 votes

Cela n'a pas fonctionné pour moi dans Rails 4. La solution ci-dessous par "mu is too short" fonctionne.

22 votes

rails g migration AddTimestampsToUser created_at:datetime updated_at:datetime - un raccourci pour générer la migration ci-dessus.

5 votes

L'exécution de cette migration entraîne une erreur PG::NotNullViolation: ERROR: column "created_at" contains null value parce que ma table contient déjà des données qui violent la contrainte not null. Y a-t-il une meilleure façon de procéder que de supprimer la contrainte non nulle dans un premier temps, puis de l'ajouter plus tard ?

94voto

mu is too short Points 205090

Les migrations ne sont que deux méthodes de classe (ou méthodes d'instance en 3.1) : up y down (et parfois un change en 3.1). Vous voulez que vos changements aillent dans le up méthode :

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

Si vous êtes en 3.1, vous pouvez aussi utiliser change (merci Dave) :

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

Peut-être que vous confondez def change , def change_table y change_table .

Voir le guide de migration pour plus de détails.

1 votes

(Eh bien, il y a le change méthode maintenant, bien que dans ce cas, ce ne soit pas le problème :)

0 votes

@Dave : C'est vrai, j'ai opté pour le générique pour éviter les problèmes de version mais change mérite d'être mentionné, je vais donc l'ajouter aussi.

0 votes

C'est vrai, mais j'ai entendu dire que cela changeait vraiment avec la version 3.1 et que le "down" était en train de disparaître. Rails va trouver la méthode down automatiquement. En avez-vous entendu parler ?

77voto

georgebrock Points 9582

Votre code original est très proche du bon, vous devez juste utiliser un nom de méthode différent. Si vous utilisez Rails 3.1 ou une version ultérieure, vous devez définir une méthode de type change au lieu de change_table :

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

Si vous utilisez une version plus ancienne, vous devez définir les paramètres suivants up y down au lieu de change_table :

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

  def down
    remove_timestamps(:users)
  end
end

39voto

Pradeep Sanjaya Points 557
class AddTimestampsToUser < ActiveRecord::Migration
  def change
    change_table :users do |t|
      t.timestamps
    end
  end
end

Les transformations disponibles sont

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

2voto

Rogier Points 3237

J'ai fait une fonction simple que vous pouvez appeler pour ajouter à chaque (en supposant que vous disposez d'une base de données existante) la table créé_at y updated_at champs :

  # 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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X