Je n'arrive pas à trouver une option ou quoi que ce soit qui me permette d'ignorer les migrations.
Je sais ce que vous pensez: "vous ne devriez jamais avoir à faire ça ..."
Je dois ignorer une migration qui modifie des enregistrements d'utilisateurs spécifiques qui n'existent pas dans ma base de développement. Je ne veux pas changer la migration car elle ne fait pas partie de la source avec laquelle je suis supposée travailler. Existe-t-il un moyen d'ignorer une migration ou les migrations échouées?
Merci d'avance!
Je pense que vous devriez corriger les migrations incriminées pour qu'elles soient moins fragiles. Je suppose que deux déclarations if
et peut-être une rescue
seraient suffisantes.
Toutefois, si la résolution des migrations n’est pas vraiment une option, vous pouvez la simuler de différentes manières. Tout d'abord, vous pouvez simplement commenter les méthodes de migration, exécuter rake db:migrate
, puis supprimer le commentaire (ou rétablir) la migration incriminée.
Vous pouvez également le simuler dans la base de données, mais ce type de chicane n'est pas recommandé à moins que vous ne sachiez ce que vous faites et que cela ne vous dérange pas de corriger manuellement les choses lorsque vous faites (inévitablement) une erreur. Il y a une table dans votre base de données appelée schema_migrations
qui a une seule colonne varchar(255)
appelée version
; db:migrate
utilise cette table pour savoir quelles migrations ont été appliquées. Il vous suffit d'insérer la valeur version
appropriée et rake db:migrate
pensera que la migration a été effectuée. Recherchez le fichier de migration incriminé:
db/migrate/99999999999999_XXXX.rb
puis allez dans votre base de données et dites:
insert into schema_migrations (version) values ('99999999999999');
où 99999999999999
est bien entendu le numéro du nom de fichier de la migration. Ensuite, exécuter rake db:migrate
devrait ignorer cette migration.
J'irais avec la deuxième option avant la troisième, je n'inclus que l'option "pirater schema_versions
" pour la complétude.
J'ai eu un problème où j'avais une migration pour ajouter un tableau qui existait déjà, alors dans mon cas, je devais aussi ignorer cette migration, car j'avais l'erreur
SQLite3::SQLException: table "posts" already exists: CREATE TABLE "posts"
Je me suis contenté de commenter le contenu de la méthode create table, d'exécuter la migration, puis de le supprimer. C'est un moyen manuel de contourner le problème, mais cela a fonctionné. Voir ci-dessous:
class CreatePosts < ActiveRecord::Migration
def change
# create_table :posts do |t|
# t.string :title
# t.text :message
# t.string :attachment
# t.integer :user_id
# t.boolean :comment
# t.integer :phase_id
# t.timestamps
# end
end
end
C'est un bon moyen de le faire pour des erreurs uniques.
db:migrate:up VERSION=my_version
Cela exécutera les actions "up" d'une migration spécifique. (Il y a aussi le contraire si vous en avez besoin, remplacez simplement "up" par "down".) Ainsi, vous pouvez exécuter la migration future qui permet à l'ancienne (que vous devez ignorer) de fonctionner la migration devant elle de manière sélective.
Je crois aussi que vous pouvez refaire les migrations de cette façon:
rake db:migrate:redo VERSION=my_version
Je n'ai pas essayé cette méthode personnellement, donc YMMV.
Insère toutes les migrations manquantes:
def insert(xxx)
ActiveRecord::Base.connection.execute("insert into schema_migrations (version) values (#{xxx})") rescue nil
end
files = Dir.glob("db/migrate/*")
files.collect { |f| f.split("/").last.split("_").first }.map { |n| insert(n) }
parfois, il est nécessaire de remplir à nouveau la table schema_migrations
avec les migrations sont définitivement correctes ... UNIQUEMENT À CET EFFET i a créé cette méthode
def self.insert_missing_migrations(stop_migration=nil)
files = Dir.glob("db/migrate/*")
timestamps = files.collect{|f| f.split("/").last.split("_").first}
only_n_first_migrations = timestamps.split(stop_migration).first
only_n_first_migrations.each do |version|
sql = "insert into `schema_migrations` (`version`) values (#{version})"
ActiveRecord::Base.connection.execute(sql) rescue nil
end
end
vous pouvez le copier-coller dans le modèle de votre choix et l'utiliser depuis la console
YourModel.insert_missing_migrations("xxxxxxxxxxxxxx")
(ou d'une autre manière)
où "xxxxxxxxxxxxxx"
- correspond à l'horodatage de la migration avant lequel vous souhaitez arrêter l'insertion (vous pouvez le laisser vide)
!!! utilisez-le uniquement si vous comprenez absolument quel résultat vous obtiendrez !!!
Au lieu de passer la migration, vous pouvez rendre votre migration intelligente, en y ajoutant un IF, de sorte que vous puissiez vérifier les "utilisateurs spécifiques"
Pour ignorer toutes les migrations en attente, exécutez ceci dans votre terminal:
echo "a = [" $(Rails db:migrate:status | grep "down" | grep -o '[0-9]\{1,\}' | tr '\n' ', ') "];def insert(b);ActiveRecord::Base.connection.execute(\"insert into schema_migrations (version) values (#{b})\") rescue nil;end;a.map { |b| insert(b)}" | xclip
(Pour macOS, utilisez pbcopy au lieu de xclip)
Puis CTRL-V le résultat dans la console Rails:
a = [ 20180927120600,20180927120700 ];def insert(b);ActiveRecord::Base.connection.execute("insert into schema_migrations (version) values (#{b})") rescue nil;end;a.map { |b| insert(b)}
Et appuyez sur ENTER.
Vous pouvez modifier la liste des migrations que vous souhaitez ignorer en les supprimant du tableau a avant d'exécuter la ligne.