80 votes

La restauration de l'échec d'un rails de la migration

Comment faire reculer l'échec d'un rails de la migration? Je m'attends à ce que le rake db:rollback aurait pour effet d'annuler l'échec de la migration, mais non, elle annule la précédente migration (l'échec de la migration moins un). Et rake db:migrate:VERSION=myfailedmigration ne fonctionne pas non plus. J'ai couru dans ce à quelques reprises et c'est très frustrant. Voici un test simple que j'ai fait pour reproduire le problème:

class SimpleTest < ActiveRecord::Migration
  def self.up
    add_column :assets, :test, :integer
    # the following syntax error will cause the migration to fail
    add_column :asset, :test2, :integer
  end

  def self.down
    remove_column :assets, :test
    remove_column :assets, :test2
  end
end

résultat:

== SimpleTest: migration =====================================================
-- add_column(:actifs :test :integer)
 -> 0.0932 s
-- add_column(:actif :erreur)
râteau abandonnée!
Une erreur s'est produite, tous les migrations annulé:

mauvais nombre d'arguments (2 de 3)

ok, permet de rouler en arrière:

$ rake db:rollback
== AddLevelsToRoles: le retour ===============================================
-- remove_column(:rôles :le niveau)
 -> 0.0778 s
== AddLevelsToRoles: revenue (0.0779 s) ======================================

hein? c'était ma dernière migration avant de SimpleTest, pas l'échec de la migration. (Et oh, ce serait bien si la migration de sortie inclus le numéro de version.)

Donc, nous allons essayer de course vers le bas pour l'échec de migration SimpleTest:

$ rake db:migrate:VERSION=20090326173033
$

Rien ne se passe, et pas de sortie non plus. Mais peut-être, il a couru à la migration de toute façon? Donc permet de corriger l'erreur de syntaxe dans le SimpleTest la migration, et d'essayer de l'exécuter à nouveau.

$ rake db:migrate:VERSION=20090326173033
== SimpleTest: migration =====================================================
-- add_column(:actifs :test :integer)
râteau abandonnée!
Mysql::Erreur: Duplicate nom de la colonne "test": ALTER TABLE `actifs` AJOUTER `test` int(11)

Nope. Évidemment, la migration:en bas ne fonctionne pas. Ce n'est pas faute, il est juste pas en cours d'exécution.

Pas moyen de se débarrasser de cette double table autres que manuellement en allant dans la base de données et de les retirer, et puis en exécutant le test. Il doit y avoir une meilleure façon que cela.

77voto

Luke Francl Points 11707

Malheureusement, vous devez nettoyer manuellement échec de la migration de MySQL. MySQL ne supporte pas de base de données transactionnelle changement de la définition.

Rails 2.2 comprend transactionnelles migrations pour PostgreSQL. Rails 2.3 comprend transactionnelles migrations pour SQLite.

Ce n'est pas vraiment vous aider pour votre problème à l'heure actuelle, mais si vous avez le choix de la base de données sur les projets futurs, je vous recommande d'utiliser celui avec le soutien de transactionnelles DDL, car elle rend les migrations beaucoup plus agréable.

20voto

MarkusQ Points 15612

Pour vous rendre à une version suffit d'utiliser:

rake db:migrate VERSION=(the version you want to go to)

Mais si un échec de la migration partie de la route, vous aurez à nettoyer en premier. Un autre moyen serait:

  • modifier l' down méthode de la migration de simplement annuler la partie de l' up qui a travaillé
  • migrer retour à l'état antérieur (là où tout a commencé)
  • fixer la migration (y compris l'annulation de vos modifications à l' down)
  • essayez à nouveau

18voto

sbwoodside Points 3860

OK, les gars, voici comment vous le faire réellement. Je ne sais pas ce que les réponses ci-dessus sont en train de parler.

  1. Figure quelle partie de la migration travaillé. Commentaire ceux.
  2. Aussi commentaire/enlever la partie de la migration qui s'est brisé.
  3. Exécutez à nouveau la migration. Maintenant il va terminer la non-rupture de la migration, en sautant les parties qui ont déjà été fait.
  4. Décommentez les bits de la migration, vous commentée dans l'étape 1.

Vous pouvez migrer en bas et en arrière de nouveau si vous voulez vérifier que vous avez maintenant.

12voto

StefanH Points 193

Je suis d'accord que vous devez utiliser PostgreSQL lorsque cela est possible. Toutefois, lorsque vous êtes coincé avec MySQL, vous pouvez éviter la plupart de ces problèmes en essayant de la migration de votre base de données de test en premier:

rake db:migrate RAILS_ENV=test

Vous pouvez revenir à l'état précédent et essayez de nouveau avec

rake db:schema:load RAILS_ENV=test

8voto

BryanH Points 2725

Le moyen facile de le faire est d'envelopper l'ensemble de vos actions dans une transaction:

class WhateverMigration < ActiveRecord::Migration

 def self.up
    ActiveRecord::Base.transaction do
...
    end
  end

  def self.down
    ActiveRecord::Base.transaction do
...
    end
  end

end

Comme Luke Francl a noté, "MySql['tables MyISAM ne pas prendre en charge les transactions" -- ce qui est pourquoi vous pourriez envisager d'éviter MySQL en général, ou au moins MyISAM en particulier.

Si vous utilisez MySQL InnoDB, puis le ci-dessus fonctionne très bien. Toute erreur dans l', soit vers le haut ou le bas du dos.

ÊTRE CONSCIENT de certains types d'actions ne peut pas être annulée par des opérations. Généralement, le tableau des modifications (suppression d'une table, d'enlever ou d'ajouter des colonnes, etc.) ne peut pas être annulée.

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