I need to migrate some data. I need to decrypt some fields (and that's no problem) but when I'm done I need to update the model to use a different strategy for the data access.
Is there a way to avoid two deployments? (One for the migration and one for the model update after the migration is complete?) I need to use the old model in the migration, but then I need the new one.
You can add a dummy ActiveRecord
model within your migration. Then your migration does not depend on the original model and its implementation anymore. That allows you to update the code in the original model.
Something like this:
class MigrateFooOnBar < ActiveRecord::Migration
class Bar < ActiveRecord::Base
def foo_migration
self.foo = some_deprecated_code
end
end
def up
add_column :bars, :foo
Bar.find_each do |bar|
bar.foo_migrate
bar.save!
end
end
# ...
end
But this not solve the core problem: A migration never runs at the exact same time when your application is deployed. When you deploy an application, the steps that does the migration runs before or after switching to the new code and the Rails app`s restart.
Depending on how long your migration takes - and it could run for minutes (and hours) on big tables - your app will face the situation in which it runs old code on a newer database schema, or has to run new code on an old database schema.
To avoid taking the app offline when running such migrations you will have to deploy multiple steps: