Transactions in Rails data migrations
Just found a useful idea in my friend’s code: use transactions in database migrations. This can save you a lot of trouble with partially updated data.
I have 2 major types of DB migrations in my Rails applications:
- Schema changes: adding columns, creating tables, etc.
- Data modifications: creating new records, fixing bad data, etc.
Occasionally I have really huge and ugly multi-step data modifications with loops, conditions, method calls, etc. And often times while testing them they fail right in the middle… Duh! Then I fix the migration and run it again, but the half the data was already fixed, so the migration fails again.
Sounds familiar?
For such data migrations it makes sense to use transactions. Even if migration fails in the middle — no problem, all changes that were already made would be cancelled.
Example of a nasty data migration with transaction:
class MigrateToNewPageStructure < Migration
def up
ActiveRecord::Base.transaction do
page.find_each do |page|
update_page(page)
end
end
def down
# Migration down is impossible nor needed.
end
private
def update_page(page)
# doesn't matter what happens here
end
end
The code snippet above was extracted from my wife’s website: http://www.alkalinemorning.com/. Update: my wife’s website now runs on Shopify platform, so this code is no longer used.
Happy software construction!