86 votes

Mettre à jour une colonne à la valeur d'une autre dans la migration Rails

J'ai une table dans une application Rails avec des centaines de milliers d'enregistrements, et ils ont seulement un created_at timestamp. Je vais ajouter la possibilité de modifier ces enregistrements, alors je veux ajouter un updated_at timestamp de la table. Dans ma migration pour ajouter la colonne, je veux mettre à jour toutes les lignes de la nouvelle updated_at correspondre à l'ancien created_at, puisque c'est la valeur par défaut pour les lignes créées dans les Rails. Je pourrais faire un find(:all) et parcourir les dossiers, mais cela pourrait prendre des heures en raison de la taille de la table. Ce que je veux vraiment faire est:

UPDATE table_name SET updated_at = created_at;

Est-il une plus belle façon de le faire que dans un Rails de la migration à l'aide de ActiveRecord plutôt que de l'exécuter SQL brut?

160voto

nathanvda Points 25878

Je créerais une migration

 rails g migration set_updated_at_values
 

et à l'intérieur, écrivez quelque chose comme:

 class SetUpdatedAt < ActiveRecord::Migration
  def self.up
    Yourmodel.connection.execute("update your_models set updated_at=created_at")
  end

  def self.down
  end
end
 

De cette façon, vous réalisez deux choses

  • c'est un processus reproductible, avec chaque déploiement possible (si nécessaire), il est exécuté
  • c'est efficace. Je ne peux pas penser à une solution plus rubyesque (aussi efficace).

J'espère que cela t'aides.

21voto

Greg Dan Points 2667

Vous pouvez utiliser update_all, qui fonctionne de manière très similaire au SQL brut. C'est toutes les options que vous avez.

BTW personnellement, je ne fais pas très attention aux migrations. Parfois, le SQL brut est vraiment la meilleure solution. Généralement, le code de migration n'est pas réutilisé. C'est une action unique, donc je ne me soucie pas de la pureté du code.

-5voto

ghoppe Points 10004

Comme une opération ponctuelle, je le ferais simplement dans les rails console . Est-ce que ça va vraiment prendre des heures? Peut-être que s'il y a des millions de disques…

records = ModelName.all; records do |r|; r.update_attributes(:updated_at => r.created_at); r.save!; 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