Cofnięcie nieudanej migracji Rails
Jak cofnąć nieudaną migrację rails? Spodziewałbym się, że rake db:rollback
cofnie nieudaną migrację, ale nie, cofnie poprzednią migrację (nieudana migracja minus jeden). I rake db:migrate:down VERSION=myfailedmigration
też nie działa. Wpadłem na to kilka razy i to jest bardzo frustrujące. Oto prosty test, który zrobił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: migrating ===================================================== -- add_column(:assets, :test, :integer) -> 0.0932s -- add_column(:asset, :error) rake aborted! An error has occurred, all later migrations canceled: wrong number of arguments (2 for 3)
Ok, cofnijmy to:
$ rake db:rollback == AddLevelsToRoles: reverting =============================================== -- remove_column(:roles, :level) -> 0.0778s == AddLevelsToRoles: reverted (0.0779s) ======================================Co? to była moja ostatnia migracja przed SimpleTest, nie nieudana migracja. (I byłoby miło, gdyby wyjście migracji zawierało numer wersji.)
Więc spróbujmy uruchomić down dla nieudanej migracji SimpleTest:
$ rake db:migrate:down VERSION=20090326173033 $
Nic się nie dzieje i nie ma wyjścia. Ale może i tak przeprowadził migrację? Więc pozwala naprawić błąd składni w najprostszej migracji, i spróbować uruchomić go ponownie.
$ rake db:migrate:up VERSION=20090326173033 == SimpleTest: migrating ===================================================== -- add_column(:assets, :test, :integer) rake aborted! Mysql::Error: Duplicate column name 'test': ALTER TABLE `assets` ADD `test` int(11)Nie. Oczywiście migrate: down nie działa. Nie zawodzi, po prostu nie wykonuje.
Nie sposób pozbyć się tej zduplikowanej tabeli poza ręcznym wejściem do bazy danych i usunięciem jej, a następnie uruchomieniem testu. Musi być lepszy sposób.
9 answers
Niestety, musisz ręcznie wyczyścić nieudane migracje dla MySQL. MySQL nie obsługuje zmian definicji transakcyjnych baz danych.
Rails 2.2 zawiera migracje transakcyjne dla PostgreSQL. Rails 2.3 zawiera migracje transakcyjne dla SQLite.
To naprawdę nie pomaga na twój problem w tej chwili, ale jeśli masz wybór bazy danych o przyszłych projektach, polecam użycie jednej z obsługą transakcji DDL, ponieważ sprawia, że migracje znacznie więcej miło.
Aktualizacja - to nadal prawda w 2017, on Rails 4.2.7 i MySQL 5.7, zgłoszone przez Alejandro Babio w innej odpowiedzi tutaj.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-05 19:10:33
Aby przejść do określonej wersji wystarczy użyć:
rake db:migrate VERSION=(the version you want to go to)
Ale jeśli migracja zawiedzie częściowo, musisz ją najpierw wyczyścić. Jednym ze sposobów byłoby:
- edytuj metodę migracji
down
, aby cofnąć częśćup
, która zadziałała - migracja z powrotem do poprzedniego stanu (od którego zacząłeś)
- napraw migrację (w tym cofanie zmian do
down
) - spróbuj ponownie
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-26 18:00:38
Ok, ludzie, oto jak to się robi. Nie wiem, o czym mówią powyższe odpowiedzi.
- Dowiedz się, która część migracji up zadziałała. Skomentuj to.
- również skomentuj / usuń część migracji, która się zepsuła.
- Uruchom migrację ponownie. Teraz zakończy niezłamane części migracji, pomijając części, które już zostały zrobione.
- odkomentuj fragmenty migracji, które skomentowałeś w kroku 1.
Możesz przenieść w dół i utworzyć kopię zapasową, jeśli chcesz sprawdzić, czy masz ją teraz.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-29 01:01:15
Zgadzam się, że powinieneś używać PostgreSQL, jeśli to możliwe. Jednak, gdy utkniesz z MySQL, możesz uniknąć większości tych problemów, próbując najpierw migracji na testowej bazie danych:
rake db:migrate RAILS_ENV=test
Możesz powrócić do poprzedniego stanu i spróbować ponownie za pomocą
rake db:schema:load RAILS_ENV=test
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-10 10:09:53
W 2015 roku z Rails 4.2.1 i MySQL 5.7, nieudana migracja nie może być naprawiona za pomocą standardowych akcji rake, które rails zapewniają, Jak to było w 2009 roku.
MySql nie obsługuje wycofywania Stanów DDL (w MySQL 5.7 Manual ). A Rails nie może nic z tym zrobić.
Możemy również sprawdzić, jak Rails wykonuje zadanie: migracja jest zawinięta w transakcję w zależności od tego, jak adapter reaguje na :supports_ddl_transactions?
. Po przeszukaniu tej akcji w Rails source (v 4.2.1), odkryłem, że tylko Sqlite3 i PostgreSql obsługuje transakcje, a przez domyślnie nie jest obsługiwany.
Edit Tak więc aktualna odpowiedź na pierwotne pytanie: nieudana migracja MySQL musi być ręcznie naprawiona.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-03 15:12:21
Łatwy sposób na to, aby to zrobić, to zawinąć wszystkie swoje działania w transakcję:
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, " MySql ['s MyISAM tables don' t] support transactions " - dlatego możesz rozważyć unikanie MySQL w ogóle lub przynajmniej MyISAM w szczególności.
Jeśli używasz InnoDB MySQL, to powyższe będzie działać dobrze. Wszelkie błędy w górę lub w dół wycofają się.
Należy pamiętać niektóre rodzaje akcji nie mogą być cofnięte poprzez transakcje. Ogólnie, zmiany tabeli (upuszczanie tabeli, usuwanie lub dodawanie kolumn itp.)nie można cofnąć.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-01 17:41:30
Uruchom tylko migrację down z konsoli:
Http://gilesbowkett.blogspot.com/2007/07/how-to-use-migrations-from-console.html (click through to his pastie)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-24 22:37:05
Miałem literówkę (w "add_column"):
Def self.up
add_column :medias, :title, :text add_colunm :medias, :enctype, :text
End
Def self.down
remove_column :medias, :title remove_column :medias, :enctype
End
A następnie twój problem(nie można cofnąć częściowo nieudanej migracji). po jakimś nieudanym googlowaniu uruchomiłem to:
Def self.up
remove_column :medias, :title add_column :medias, :title, :text add_column :medias, :enctype, :text
End
Def self.down
remove_column :medias, :title remove_column :medias, :enctype
End
Jak widzisz, dodałem linię korekcji ręcznie, a następnie usunąłem ją ponownie, zanim sprawdziłem.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-02 10:04:42
Powyższa odpowiedź Alejandro Babio zapewnia najlepszą aktualną odpowiedź.
Jeden dodatkowy szczegół chcę dodać:
Gdy migracja myfailedmigration
nie powiedzie się, nie jest uważana za zastosowaną i można to sprawdzić uruchamiając rake db:migrate:status
, które wyświetli wynik podobny do następującego:
$ 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
po nieudanej migracji będzie musiał zostać odwrócony na poziomie bazy danych za pomocą zapytania alter table assets drop column test;
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-01 18:07:02