L'assistant d'horodatage n'est disponible que dans le 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 que cela n'ait pas la même syntaxe laconique que la add_timestamps
méthode que vous avez spécifiée ci-dessus, Rails traitera toujours ces colonnes comme des colonnes d'horodatage et mettra à jour les valeurs normalement.
rails g migration AddTimestampsToUser created_at:datetime updated_at:datetime
- un raccourci pour générer la migration ci-dessus.PG::NotNullViolation: ERROR: column "created_at" contains null value
car ma table contient déjà des données qui violent la contrainte non nulle. Une meilleure façon de faire cela que de supprimer la contrainte non nulle dans un premier temps, puis de l'ajouter plus tard?add_column :users, :updated_at, :datetime, null: false, default: Time.zone.now
.Time.zone.now
est juste un exemple, vous devez utiliser la valeur qui convient à votre logique.Les migrations ne sont que deux méthodes de classe (ou méthodes d'instance dans 3.1):
up
etdown
(et parfois unechange
méthode d'instance dans 3.1). Vous souhaitez que vos modifications soient intégrées à laup
méthode:Si vous êtes dans 3.1, vous pouvez également utiliser
change
(merci Dave):Peut-être vous êtes confus
def change
,def change_table
etchange_table
.Consultez le guide de migration pour plus de détails.
la source
change
méthode maintenant, bien que dans ce cas, pas le problème :)change
vaut la peine d'être mentionné, je vais donc l'ajouter aussi.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
change
méthode au lieu dechange_table
:Si vous utilisez une version plus ancienne, vous devez définir
up
et desdown
méthodes au lieu dechange_table
:la source
La réponse de @ user1899434 a retenu le fait qu'une table "existante" ici pourrait signifier une table contenant déjà des enregistrements, des enregistrements que vous ne voudriez peut-être pas supprimer. Ainsi, lorsque vous ajoutez des horodatages avec null: false, qui est la valeur par défaut et souvent souhaitable, ces enregistrements existants sont tous invalides.
Mais je pense que cette réponse peut être améliorée, en combinant les deux étapes en une seule migration, ainsi qu'en utilisant la méthode plus sémantique add_timestamps:
Vous pouvez remplacer un autre horodatage
DateTime.now
, par exemple si vous vouliez que les enregistrements préexistants soient créés / mis à jour à l'aube des temps à la place.la source
Time.zone.now
c'est ce qui devrait être utilisé si nous voulons que notre code obéisse au fuseau horaire correct.Time.zone.now
laquelle il renverra l'instance Time qui est créée lorsque la migration est exécutée et utilise simplement cette heure comme valeur par défaut. Les nouveaux objets n'obtiendront pas de nouvelle instance Time.Les transformations disponibles sont
http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/Table.html
la source
La réponse de Nick Davies est la plus complète en termes d'ajout de colonnes d'horodatage à une table avec des données existantes. Son seul inconvénient est qu'il augmentera
ActiveRecord::IrreversibleMigration
sur undb:rollback
.Il doit être modifié ainsi pour fonctionner dans les deux sens:
la source
change_column_default
cela ne prend pas en chargefrom
etto
dans cette version?), Mais j'ai pris cette idée et créé desup/down
méthodes au lieu d'une seulechange
méthode et cela a fonctionné comme un charme!la source
Je ne sais pas exactement quand cela a été introduit, mais dans les rails 5.2.1, vous pouvez le faire:
pour en savoir plus, consultez « Utilisation de la méthode de modification » dans la documentation sur les migrations d'enregistrements actifs.
la source
, null: true
après le:my_table
J'ai créé une fonction simple que vous pouvez appeler pour ajouter à chaque table (en supposant que vous avez une base de données existante) les champs created_at et updated_at :
la source
Ajoute des colonnes d'horodatage (created_at et updated_at) à nom_table. Des options supplémentaires (comme null: false) sont transmises à #add_column.
la source
Les réponses précédentes semblent correctes, mais j'ai rencontré des problèmes si ma table contient déjà des entrées.
J'obtiendrais «ERREUR: la colonne
created_at
contient desnull
valeurs».Pour réparer, j'ai utilisé:
J'ai ensuite utilisé le gem migration_data pour ajouter le temps des projets en cours sur la migration tels que:
Ensuite, tous les projets créés après cette migration seront correctement mis à jour. Assurez-vous que le serveur est également redémarré afin que Rails
ActiveRecord
commence à suivre les horodatages sur l'enregistrement.la source
Beaucoup de réponses ici, mais je posterai la mienne aussi car aucune des précédentes n'a vraiment fonctionné pour moi :)
Comme certains l'ont noté,
#add_timestamps
ajoute malheureusement lanull: false
restriction, ce qui rendra les anciennes lignes invalides car elles n'ont pas ces valeurs remplies. La plupart des réponses ici suggèrent que nous définissions une valeur par défaut (Time.zone.now
), mais je n'aimerais pas le faire car ces horodatages par défaut pour les anciennes données ne seront pas corrects. Je ne vois pas l'intérêt d'ajouter des données incorrectes à la table.Ma migration était donc simplement:
Non
null: false
, pas d'autres restrictions. Les anciennes lignes continueront d'être valides aveccreated_at
asNULL
etupdate_at
asNULL
(jusqu'à ce qu'une mise à jour soit effectuée sur la ligne). Les nouvelles lignes aurontcreated_at
et serontupdated_at
remplies comme prévu.la source
Le problème avec la plupart des réponses ici est que si vous par défaut,
Time.zone.now
tous les enregistrements auront l'heure à laquelle la migration a été exécutée comme heure par défaut, ce qui n'est probablement pas ce que vous voulez. Dans les rails 5, vous pouvez utiliser à la placenow()
. Cela définira les horodatages pour les enregistrements existants comme l'heure à laquelle la migration a été exécutée et comme l'heure de début de la transaction de validation pour les enregistrements nouvellement insérés.class AddTimestampsToUsers < ActiveRecord::Migration def change add_timestamps :users, default: -> { 'now()' }, null: false end end
la source
L'utilisation
Time.current
est un bon style https://github.com/rubocop-hq/rails-style-guide#timenowou
la source
Ceci est simple pour ajouter un horodatage dans une table existante.
la source
Pour ceux qui n'utilisent pas Rails mais utilisent activerecord, ce qui suit ajoute également une colonne à un modèle existant, par exemple pour un champ entier.
la source
Ce n'est
change
paschange_table
pour Rails 4.2:la source
Cela semble être une solution propre dans Rails 5.0.7 (découverte de la méthode change_column_null):
la source
Je suis sur les rails 5.0 et aucune de ces options n'a fonctionné.
La seule chose qui fonctionnait était d'utiliser le type à être: timestamp et non: datetime
la source
J'ai personnellement utilisé ce qui suit, et il a mis à jour tous les enregistrements précédents avec l'heure / la date actuelle:
la source
J'ai rencontré le même problème sur Rails 5 en essayant d'utiliser
J'ai pu ajouter les colonnes d'horodatage manuellement avec les éléments suivants:
la source