Jak przywrócić nieudaną migrację szyn? Spodziewałbym się, rake db:rollback
że cofnie to nieudaną migrację, ale nie, cofa poprzednią migrację (nieudana migracja minus jedna). I rake db:migrate:down VERSION=myfailedmigration
też nie działa. Spotkałem się z tym kilka razy i jest to bardzo frustrujące. Oto prosty test, który wykonałem, aby zduplikować problem:
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
wynik:
== SimpleTest: migracja ============================================= ======== - add_column (: asset,: test,: integer) -> 0,0932 s - add_column (: asset,: error) prowizja przerwana! Wystąpił błąd, wszystkie późniejsze migracje zostały anulowane: zła liczba argumentów (2 za 3)
ok, cofnijmy to:
$ rake db: rollback == AddLevelsToRoles: przywracanie =============================================== == - remove_column (: role,: level) -> 0,0778 s == AddLevelsToRoles: przywrócone (0,0779s) ========================================
co? to była moja ostatnia migracja przed SimpleTest, a nie nieudana migracja. (I och, byłoby miło, gdyby dane wyjściowe migracji zawierały numer wersji).
Spróbujmy więc uruchomić wyłączenie dla nieudanej migracji SimpleTest:
$ rake db: migrate: down WERSJA = 20090326173033 $
Nic się nie dzieje i nie ma też wyjścia. Ale może i tak przeprowadził migrację? Więc naprawmy błąd składni w migracji SimpleTest i spróbujmy go ponownie uruchomić.
$ rake db: migrate: up WERSJA = 20090326173033 == SimpleTest: migracja ============================================= ======== - add_column (: asset,: test,: integer) prowizja przerwana! MySQL :: Błąd: zduplikowana nazwa kolumny 'test': ALTER TABLE `asset` ADD` test` int (11)
Nie. Oczywiście migrate: down nie zadziałało. Nie zawodzi, po prostu się nie wykonuje.
Nie ma innego sposobu na pozbycie się tej zduplikowanej tabeli niż ręczne wejście do bazy danych i usunięcie jej, a następnie uruchomienie testu. Musi być lepszy sposób niż to.
źródło
Aby przejść do określonej wersji, użyj:
Ale jeśli migracja nie powiedzie się częściowo, musisz ją najpierw wyczyścić. Jednym ze sposobów byłoby:
down
metodę migracji, aby po prostu cofnąć tę część,up
która działaładown
)źródło
OK, ludzie, oto jak to robicie. Nie wiem, o czym mówią powyższe odpowiedzi.
Możesz przeprowadzić migrację w dół i ponownie utworzyć kopię zapasową, jeśli chcesz sprawdzić, czy masz ją teraz.
źródło
bundle exec rake db:migrate:redo
. Będzie to krok wstecz i krok do przodu, dzięki czemu możesz sprawdzić, czy ostatnia migracja przebiega przez cały czas. Jest to dobra praktyka za każdym razem, gdy musisz wypchnąć migrację wraz z niektórymi aktualizacjami kodu.Zgadzam się, że powinieneś używać PostgreSQL, jeśli to możliwe. Jeśli jednak utkniesz z MySQL, możesz uniknąć większości tych problemów, próbując najpierw przeprowadzić migrację na testowej bazie danych:
Możesz powrócić do poprzedniego stanu i spróbować ponownie za pomocą
rake db:schema:load RAILS_ENV=test
źródło
W 2015 roku z Railsami 4.2.1 i MySQL 5.7 nieudanej migracji nie można naprawić za pomocą standardowych akcji rake, które zapewniają Railsy, tak jak to było w 2009 roku.
MySql nie obsługuje wycofywania instrukcji DDL (w podręczniku MySQL 5.7 ). A Railsy nie mogą nic z tym zrobić.
Możemy również sprawdzić, jak Railsy wykonują swoją pracę: migracja jest opakowana w transakcję w zależności od odpowiedzi adaptera połączenia
:supports_ddl_transactions?
. Po przeszukaniu tej akcji w źródłach railsowych (v 4.2.1) stwierdziłem, że tylko Sqlite3 i PostgreSql obsługują transakcje i domyślnie nie są obsługiwane.Edycja Zatem aktualna odpowiedź na pierwotne pytanie: Nieudana migracja MySQL musi zostać naprawiona ręcznie.
źródło
Najłatwiejszym sposobem na to jest zawarcie wszystkich działań w transakcji:
class WhateverMigration < ActiveRecord::Migration def self.up ActiveRecord::Base.transaction do ... end end def self.down ActiveRecord::Base.transaction do ... end end end
Jak zauważył Luke Francl, „Tabele MySql [w MyISAM] nie obsługują transakcji” - dlatego warto rozważyć ogólne unikanie MySQL lub przynajmniej MyISAM w szczególności.
Jeśli używasz InnoDB MySQL, powyższe będzie działać dobrze. Wszelkie błędy w górę lub w dół zostaną wycofane.
UWAŻAJ na niektóre rodzaje działań nie można cofnąć za pośrednictwem transakcji. Ogólnie rzecz biorąc, zmian w tabeli (upuszczanie tabeli, usuwanie lub dodawanie kolumn itp.) Nie można cofnąć.
źródło
Uruchom tylko migrację w dół z konsoli:
http://gilesbowkett.blogspot.com/2007/07/how-to-use-migrations-from-console.html (kliknij, aby przejść do jego ciasta)
źródło
Wystąpiła literówka (w „add_column”):
a następnie problem (nie można cofnąć częściowo nieudanej migracji). po kilku nieudanych googlach uruchomiłem to:
jak widać, po prostu ręcznie dodałem linię korekty, a następnie usunąłem ją ponownie, zanim ją sprawdziłem.
źródło
Odpowiedź Alejandro Babio powyżej zapewnia najlepszą aktualną odpowiedź.
Jeszcze jeden szczegół, który chcę dodać:
Gdy
myfailedmigration
migracja się nie powiedzie, nie jest uznawana za zastosowaną i można to zweryfikować, uruchamiającrake db:migrate:status
, co spowoduje wyświetlenie wyników podobnych do następujących:$ rake db:migrate:status database: sample_app_dev Status Migration ID Migration Name -------------------------------------------------- up 20130206203115 Create users ... ... down 20150501173156 Test migration
Pozostały efekt
add_column :assets, :test, :integer
wykonania nieudanej migracji będzie musiał zostać odwrócony na poziomie bazy danych za pomocąalter table assets drop column test;
zapytania.źródło