Когда приемлемо поднимать исключение ActiveRecord:: IrreversibleMigration в методе self.down миграции? Когда вы должны предпринять усилия для фактического осуществления обратной миграции?
Rails: Плохо ли иметь необратимую миграцию?
Ответ 1
Если вы имеете дело с системами производственного класса, то да, это очень плохо. Если это ваш собственный проект для домашних животных, тогда разрешено что-либо (если ничего другого, это будет опыт обучения:) хотя есть вероятность, что раньше, чем позже, даже в проекте с домашним животным, вы обнаружите, что поставили крест над обратная миграция только для того, чтобы отменить эту миграцию через несколько дней, будь то через rake
или вручную.)
В сценарии производства вы должны всегда прилагать усилия для написания и проверки обратимой миграции в случае, если вы пройдете через нее в процессе производства, а затем обнаружите ошибку, которая заставляет вас откатиться ( код и схема) до некоторой предыдущей версии (в ожидании некоторого нетривиального исправления) и в противном случае непригодной производственной системы.)
Обратные миграции варьируются от тривиальных (удаление столбцов или таблиц, добавленных во время миграции, и/или изменение типов столбцов и т.д.) в несколько более активное участие (execute
of JOIN
ed INSERT
или UPDATE
s), но ничто не является настолько сложным, чтобы оправдать "подметание его под ковриком". Если ничто иное, заставляя себя думать о способах достижения обратных миграций, может дать вам новое представление о самой проблеме, которую исправляет ваша передовая миграция.
Иногда вы можете столкнуться с ситуацией, когда перенаправление миграции удаляет функцию, в результате чего данные удаляются из базы данных. По очевидным причинам обратная миграция не может реанимировать отброшенные данные.. Хотя в таких случаях можно было бы рекомендовать, чтобы перенаправленная миграция автоматически сохраняла данные или сохраняла их в случае отката в качестве альтернативы прямому (сохранить в yml
, скопировать/переместить в специальную таблицу и т.д.), вам не нужно, поскольку время, необходимое для тестирования такой автоматизированной процедуры, может превышать время, необходимое для восстановления данных вручную (если возникает необходимость.) Но даже в таких случаях вместо простого вы всегда можете сделать обратную миграцию условно и временно отказываться в ожидании некоторого действия пользователя (т.е. проверить наличие какой-либо требуемой таблицы, которая должна восстанавливать вручную, если отсутствует, вывод "Я потерпел неудачу, потому что не могу воссоздать таблицу XYZ
из ничего, вручную восстановить таблицу XYZ
из резервной копии, а затем запустить меня снова, и я не подведу вас!" )
Ответ 2
Если вы уничтожаете данные, сначала можете сделать резервную копию. например.
def self.up
# create a backup table before destroying data
execute %Q[create table backup_users select * from users]
remove_column :users, :timezone
end
def self.down
add_column :users, :timezone, :string
execute %Q[update users U left join backup_users B on (B.id=U.id) set U.timezone = B.timezone]
execute %Q[drop table backup_users]
end
Ответ 3
В сценарии производства вы всегда должны стараться писать и тестировать обратимую миграцию в случае, если вы проходите ее в процессе производства, а затем обнаруживаете ошибку, которая заставляет вас откатываться (код и схема) к некоторым предыдущим (в ожидании некоторого нетривиального исправления) и в противном случае непригодной производственной системы.)
Реверсивная миграция прекрасна для разработки и постановки, но при условии хорошо протестированного кода это должно быть крайне редко, что вы когда-либо захотите мигрировать в производство. Я встраиваю в свои миграции автоматическую IrreversibleMigration в режиме производства. Если мне действительно нужно отменить изменение, я мог бы использовать другую миграцию "вверх" или удалить исключение. Это кажется отрывочным. Любая ошибка, которая может привести к сценарию этого ужаса, является признаком того, что процесс QA серьезно запутан.
Ответ 4
Чувство, будто вам нужно необратимое перемещение, вероятно, является признаком того, что у вас возникают большие проблемы. Может быть, некоторые особенности помогут?
Что касается вашего второго вопроса: я всегда беру "усилие", чтобы написать обратную миграцию. Конечно, я на самом деле не пишу .down
, TextMate автоматически вставляет его при создании .up
.
Ответ 5
Реверсивная миграция данных позволяет легко создавать обратимые миграции данных с использованием файлов yaml.
class RemoveStateFromProduct < ActiveRecord::Migration
def self.up
backup_data = []
Product.all.each do |product|
backup_data << {:id => product.id, :state => product.state}
end
backup backup_data
remove_column :products, :state
end
def self.down
add_column :products, :state, :string
restore Product
end
end
Ответ 6
IIRC, вы будете иметь IrreversibleMigration при изменении типа данных при переносе.
Ответ 7
Я думаю, что еще одна ситуация, когда это нормально, когда у вас сводная миграция. В этом случае "вниз" на самом деле не имеет смысла, так как он потеряет все таблицы (кроме таблиц, добавленных после консолидации). Вероятно, это не то, что вам нужно.