Transactions in Rails data migrations

Posted on 2014-3-29 by Alex

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.

Person givin a credit card to a computer

I have 2 major types of DB migrations in my Rails applications:

  1. Schema changes: adding columns, creating tables, etc.
  2. 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!