59 Stimmen

Was ist der beste Weg, verwaiste Rails-Migrationen zu lösen?

Ich habe zwischen verschiedenen Branches in einem Projekt gewechselt und jeder von ihnen hat unterschiedliche Migrationen... Dies ist das Szenario:

$ rake db:migrate:status

 Status   Migration ID    Migration Name
--------------------------------------------------
   ...
   up     20130307154128  Spaltenänderung in Traffic-Capture
   up     20130311155109  Log-Einstellungen entfernen
   up     20130311160901  Log-Alarm-Tabelle entfernen
   up     20130320144219  ********** KEINE DATEI **********
   up     20130320161939  ********** KEINE DATEI **********
   up     20130320184628  ********** KEINE DATEI **********
   up     20130322004817  Replikat zu Root-Einstellungen hinzufügen
   up     20130403190042  ********** KEINE DATEI **********
   up     20130403195300  ********** KEINE DATEI **********
   up     20130403214000  ********** KEINE DATEI **********
   up     20130405164752  AP-Hostnamen korrigieren
   up     20130410194222  ********** KEINE DATEI **********

Das Problem ist, dass rake db:rollback überhaupt nicht funktioniert, weil die Dateien fehlen...

Was kann ich tun, um wieder rollbacks durchführen zu können und die KEINE DATEI-Nachrichten loszuwerden?

Übrigens sind rake db:reset oder rake db:drop keine Option, ich kann keine Daten aus anderen Tabellen verlieren...

3voto

Jared Punkte 2645

Hier ist eine von mir geschriebene Rechenaufgabe zu diesem Zweck. Es ruft dieselbe Methode auf, die unter der Haube von db:migrate:status verwendet wird, ActiveRecord::Base.connection.migration_context.migrations_status

# lib/tasks/cleanup_migration_entries.rake

desc 'Entfernt schema_migration Einträge für entfernte Migrationsdateien'
task 'db:migrate:cleanup': :environment do
  migration_context = ActiveRecord::Base.connection.migration_context
  versions_to_delete =
    migration_context.migrations_status
                     .filter_map { |_status, version, name| version if name.include?('NO FILE') }

  migration_context.schema_migration.delete_by(version: versions_to_delete)

  puts "Bereinigte #{versions_to_delete.size} verwaiste Migrationen."
end

1voto

Jin Lim Punkte 1298

Ich habe eine Migration dafür erstellt.

class DeleteOrphanedMigrationFile < ActiveRecord::Migration[6.0]
  def up
    db_connection = ActiveRecord::Base.connection
    migration_context = ActiveRecord::Base.connection.migration_context
    removed_file_versions = migration_context.migrations_status.filter_map { |_status, version, name| version if name.include?('KEINE DATEI') }

    removed_file_versions.each do |version|
      sql = "delete from schema_migrations where version='#{version}';"
      db_connection.execute(sql)
    end
  end

  def down; end
end

0voto

mikeryz Punkte 527

Angenommen, dass du Git verwendest, sollte es relativ einfach sein, diese Migrationen zu schnappen und in deinen aktuellen Branch zu bringen. Wenn du ein bestimmtes Commit hast, von dem du eine Datei haben möchtest, kannst du verwenden:

git checkout  

(Danke an diese Antwort)

Alternativ kannst du vom Head eines bestimmten Branches auschecken:

git checkout  -- 

Laut diesem Blog-Beitrag

Angenommen, dies sind tatsächlich die Versionen der Migrationen, die in der Datenbank ausgeführt wurden, solltest du in der Lage sein, zurückzusetzen.

0voto

Whit Kemmey Punkte 2200

Sie könnten die beiden Zweige wieder in den Master zusammenführen, so dass Sie alle Migrationen verfügbar haben. Wenn Sie diese Migrationen wirklich nicht möchten, aber trotzdem zurückrollen möchten, könnten Sie die schema_migrations-Tabelle in Ihrer Datenbank bearbeiten, um die Zeilen zu entfernen, die den Migrationen entsprechen, für die Sie keine Dateien haben. Dies wird jedoch Probleme verursachen, wenn Sie dann zu einem anderen Zweig mit anderen Migrationen wechseln.

0voto

Wenn die Migrationsdateien tatsächlich fehlen (z. B. Migration durchgeführt, vergessen, die Migration zurückzusetzen, dann die Migrationsdatei vor dem Commit gelöscht), konnte ich das Fehlen der Migration wie folgt reproduzieren:

  1. Gehen Sie im Git-Verlauf zurück, um eine Kopie der schema.rb-Datei zu erhalten und außerhalb des Git-Repositories zu speichern (git log; git checkout xxxxxx; cp schema.rb ~/schema_old.rb, git checkout master).
  2. Führen Sie einen Diff-Befehl auf den beiden Dateien aus und kopieren Sie die Migrationsbefehle in eine Migrationsdatei, die der fehlenden Migrations-ID entspricht (diff schema.rb ~/schema_old.rb > migration_file.rb; vi migration_file.rb)
  3. Überprüfen Sie den Status Ihrer Migration und führen Sie einen Rollback durch (rake db:migrate:status; rake db:rollback; rake db:migrate:status;)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X