Ajouter des horodatages à une table existante

Je dois append des horodatages (created_at updated_at) à une table existante. J’ai essayé le code suivant mais cela n’a pas fonctionné. J’ai également essayé d’autres solutions que j’ai trouvées en ligne, mais elles ne fonctionnent pas non plus.

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

Comment puis-je le faire?

    L’aide d’horodatage est uniquement disponible dans le bloc create_table . Vous pouvez append ces colonnes en spécifiant les types de colonne 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 que cette syntaxe ne soit pas identique à celle de la méthode add_timestamps spécifiée ci-dessus, Rails traitera toujours ces colonnes comme des colonnes d'horodatage et mettra à jour les valeurs normalement.

    Les migrations ne sont que deux méthodes de classe (ou méthodes d’instance dans 3.1): up et down (et parfois une méthode d’instance de change dans 3.1). Vous voulez que vos modifications entrent dans la méthode up :

     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 également utiliser le 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 et change_table .

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

    Votre code d’origine est très proche de la droite, il vous suffit d’utiliser un nom de méthode différent. Si vous utilisez Rails 3.1 ou version ultérieure, vous devez définir une méthode de change au lieu de change_table :

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

    Si vous utilisez une version antérieure, vous devez définir up méthodes up et down au lieu de change_table :

     class AddTimestampsToUser < ActiveRecord::Migration def up add_timestamps(:users) end def down remove_timestamps(:users) end end 
     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.ssortingng 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

    La réponse de @ user1899434 a pris en compte le fait qu’une table “existante” pourrait signifier une table avec des enregistrements déjà présents, des enregistrements que vous pourriez ne pas vouloir supprimer. Donc, lorsque vous ajoutez des horodatages avec la valeur null: false, ce qui est la valeur par défaut et souvent souhaitable, ces enregistrements existants sont tous non valides.

    Mais je pense que cette réponse peut être améliorée en combinant les deux étapes en une seule migration et en utilisant la méthode plus sémantique add_timestamps:

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

    Vous pouvez substituer un autre horodatage à DateTime.now , comme si vous souhaitiez créer / mettre à jour des enregistrements préexistants à la première heure.

     def change add_timestamps :table_name end 

    J’ai créé une fonction simple que vous pouvez appeler pour append à chaque table (en supposant que vous ayez une firebase database existante) les champs created_at et updated_at :

      # 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 

    add_timestamps (nom_table, options = {}) public

    Ajoute des colonnes d’horodatage (created_at et updated_at) à nom_table. Des options supplémentaires (comme null: false) sont transférées vers #add_column.

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

    Pour ceux qui n’utilisent pas Rails mais utilisent effectivement activerecord, les éléments suivants ajoutent également une colonne à un modèle existant, par exemple pour un champ entier.

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

    C’est le change , pas change_table pour Rails 4.2:

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

    Les réponses précédentes semblent correctes, mais j’ai rencontré des problèmes si ma table contenait déjà des entrées.

    J’obtiendrais «ERREUR: la colonne created_at contient null valeurs null ».

    Pour corriger, j’ai utilisé:

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

    J’ai ensuite utilisé gem migration_data pour append du temps aux projets en cours sur la migration, tels que:

     def data Project.update_all created_at: Time.now end 

    Ensuite, tous les projets créés après cette migration seront correctement mis à jour. Assurez-vous que le serveur est également redémarré pour que Rails ActiveRecord commence à suivre les horodatages de l’enregistrement.

    J’ai personnellement utilisé ce qui suit et mis à jour tous les enregistrements précédents avec l’heure / la date actuelle:

     add_column :, :created_at, :datetime, default: Time.zone.now, null: false add_column :
    , :updated_at, :datetime, default: Time.zone.now, null: false