Как отменить неудачную миграцию рельсов? Я ожидал, что rake db:rollback
это отменит неудачную миграцию, но нет, это откатит предыдущую миграцию (неудачная миграция минус один). И rake db:migrate:down VERSION=myfailedmigration
тоже не работает. Я сталкивался с этим несколько раз, и это очень расстраивает. Вот простой тест, который я провел, чтобы воспроизвести проблему:
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
результат:
== SimpleTest: перенос ============================================= ======== - add_column (: assets,: test,: integer) -> 0,0932 с - add_column (: актив,: ошибка) грабли прерваны! Произошла ошибка, все последующие миграции отменены: неправильное количество аргументов (2 вместо 3)
ок, давай откатим назад:
$ rake db: откат == AddLevelsToRoles: возврат =============================================== == - remove_column (: роли,: уровень) -> 0,0778 с == AddLevelsToRoles: возвращено (0,0779 с) ======================================
а? это была моя последняя миграция перед SimpleTest, а не неудачная миграция. (И о, было бы неплохо, если бы вывод миграции содержал номер версии.)
Итак, давайте попробуем запустить простой тест для неудачной миграции:
$ rake db: migrate: down ВЕРСИЯ = 20090326173033 $
Ничего не происходит, и выхода тоже нет. Но, может быть, он все равно выполнил миграцию? Итак, давайте исправим синтаксическую ошибку в миграции SimpleTest и попробуем запустить ее снова.
$ rake db: migrate: up VERSION = 20090326173033 == SimpleTest: перенос ============================================= ======== - add_column (: assets,: test,: integer) грабли прерваны! Mysql :: Ошибка: повторяющееся имя столбца 'test': ALTER TABLE `assets` ADD` test` int (11)
Нет. Очевидно, что migrate: down не сработал. Это не сбой, это просто не выполняется.
Нет другого способа избавиться от этой повторяющейся таблицы, кроме как вручную войти в базу данных и удалить ее, а затем запустить тест. Должен быть способ получше.
источник
Чтобы перейти к указанной версии, просто используйте:
Но если миграция не удается частично, вам придется сначала очистить ее. Один из способов:
down
метод миграции, чтобы просто отменить ту часть,up
которая сработалаdown
)источник
Хорошо, ребята, вот как вы это делаете. Я не знаю, о чем говорят приведенные выше ответы.
Вы можете выполнить миграцию вниз и снова вверх, если хотите убедиться, что у вас это есть прямо сейчас.
источник
bundle exec rake db:migrate:redo
. Он будет делать один шаг назад и один шаг вперед, так что вы можете убедиться, что ваша последняя миграция выполняется полностью. Это хорошая практика в любое время, когда вам нужно продвинуть миграцию вместе с некоторыми обновлениями кода.Я согласен с тем, что вам следует использовать PostgreSQL, когда это возможно. Однако, когда вы застряли в MySQL, вы можете избежать большинства этих проблем, попробовав сначала выполнить миграцию в тестовой базе данных:
Вы можете вернуться к предыдущему состоянию и повторить попытку с помощью
rake db:schema:load RAILS_ENV=test
источник
В 2015 году с Rails 4.2.1 и MySQL 5.7 неудачная миграция не могла быть исправлена стандартными граблями, которые предоставляет Rails, как это было в 2009 году.
MySql не поддерживает откат статусов DDL (в Руководстве по MySQL 5.7 ). И Rails с этим ничего не может поделать.
Кроме того, мы можем проверить, как Rails выполняет свою работу: миграция заключена в транзакцию в зависимости от того, как на нее отвечает адаптер подключения
:supports_ddl_transactions?
. После поиска этого действия в источнике rails (v 4.2.1) я обнаружил, что только Sqlite3 и PostgreSql поддерживают транзакции, и по умолчанию они не поддерживаются.Изменить Таким образом, текущий ответ на исходный вопрос: неудачная миграция MySQL должна быть исправлена вручную.
источник
Самый простой способ сделать это - обернуть все ваши действия в транзакцию:
class WhateverMigration < ActiveRecord::Migration def self.up ActiveRecord::Base.transaction do ... end end def self.down ActiveRecord::Base.transaction do ... end end end
Как заметил Люк Франкл, «таблицы MySql [MyISAM] не поддерживают] транзакции» - вот почему вы можете подумать об отказе от MySQL в целом или, по крайней мере, MyISAM в частности.
Если вы используете MySQL InnoDB, то вышеуказанное будет работать нормально. Любые ошибки вверх или вниз вернутся.
ВНИМАНИЕ: некоторые действия нельзя отменить с помощью транзакций. Как правило, изменения таблицы (удаление таблицы, удаление или добавление столбцов и т. Д.) Не могут быть отменены.
источник
Запустите только миграцию вниз из консоли:
http://gilesbowkett.blogspot.com/2007/07/how-to-use-migrations-from-console.html (щелкните его пасту)
источник
У меня была опечатка (в "add_column"):
а затем ваша проблема (нельзя отменить частично неудачную миграцию). после неудачного поиска в Google я запустил это:
как вы можете видеть, я просто вручную добавил строку коррекции, а затем снова удалил ее, прежде чем зарегистрировал ее.
источник
Ответ Алехандро Бабио выше дает лучший текущий ответ.
Еще одна деталь, которую я хочу добавить:
Если
myfailedmigration
миграция не выполняется, она не считается примененной, и это можно проверить, запустив ееrake db:migrate:status
, и в результате будут выведены следующие данные:$ rake db:migrate:status database: sample_app_dev Status Migration ID Migration Name -------------------------------------------------- up 20130206203115 Create users ... ... down 20150501173156 Test migration
Остаточное влияние
add_column :assets, :test, :integer
выполнения на неудачную миграцию необходимо будет отменить на уровне базы данных с помощьюalter table assets drop column test;
запроса.источник