J'ai une table dans une application Rails avec des centaines de milliers d'enregistrements, et ils n'ont qu'un horodatage created_at
. J'ajoute la possibilité de modifier ces enregistrements, donc je Je veux ajouter un horodatage updated_at
à la table. Dans ma migration pour ajouter la colonne, je veux mettre à jour toutes les lignes pour que le nouveau updated_at
corresponde à l'ancien created_at
, car c'est la valeur par défaut pour les lignes nouvellement créées dans Rails. Je pourrais faire une find(:all)
et parcourir les enregistrements, mais cela prendrait des heures en raison de la taille de la table. Ce que je veux vraiment faire c'est:
UPDATE table_name SET updated_at = created_at;
Existe-t-il une meilleure façon de le faire dans une migration Rails en utilisant ActiveRecord plutôt que d'exécuter du SQL brut?
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.update_all("updated_at=created_at")
end
def self.down
end
end
De cette façon, vous réalisez deux choses
Remarque: vous pouvez également exécuter SQL brut dans une migration, si la requête devient trop difficile à écrire en utilisant Activerecord. Écrivez simplement ce qui suit:
Yourmodel.connection.execute("update your_models set ... <complicated query> ...")
Vous pouvez utiliser pdate_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 trop attention aux migrations. Parfois, le SQL brut est vraiment la meilleure solution. Généralement, le code de migration n'est pas réutilisé. Il s'agit d'une action unique, donc je ne me soucie pas de la pureté du code.
Comme l'a écrit gregdan, vous pouvez utiliser update_all
. Vous pouvez faire quelque chose comme ça:
Model.where(...).update_all('updated_at = created_at')
La première partie est votre ensemble typique de conditions. La dernière partie indique comment effectuer les affectations. Cela produira une instruction UPDATE
, au moins dans Rails 4.
Il s'agit d'une façon générale de résoudre, sans avoir besoin de Writing Query, car les requêtes sont soumises à des risques.
class Demo < ActiveRecord::Migration
def change
add_column :events, :time_zone, :string
Test.all.each do |p|
p.update_attributes(time_zone: p.check.last.time_zone)
end
remove_column :sessions, :time_zone
end
end
Vous pouvez exécuter directement la commande suivante sur votre Rails console
ActiveRecord::Base.connection.execute("UPDATE TABLE_NAME SET COL2 = COL1")
Par exemple: je veux mettre à jour le sku de ma table d'articles avec remote_id des tables d'articles. la commande sera la suivante:ActiveRecord::Base.connection.execute("UPDATE items SET sku = remote_id")