Skip to content
Create a gist now

Instantly share code, notes, and snippets.

# This is a mechanism we use often in our migrations. When we have a migration
# that hits every record of a large table, this looping mechanism takes the
# bite away from the migration. This allows us to be transactional in our
# migration while avoiding aggressive locking of the table. Ultimately
# allowing us to do migratory deployments even more frequently during high
# usage areas of the day.
# Further, some long migrations that we'd run over a weekend may exceed the
# max transaction time set on our MySQL server. Running smaller transactions
# avoids this sensible restriction.
# We place this bit of code in config/initializers. Transactional loop requires
# will_paginate to execute.
class ActiveRecord::Migration
def self.transactional_loop(active_record_class, paginate_options={}, &block)
page = 1
loop do
no_more_records = true
active_record_class.transaction do
active_record_class.paginate({:page => page, :per_page => 100}.merge(paginate_options)).each do |active_record_instance|
no_more_records = false
page += page + 1
break if no_more_records
class SomeMigration < ActiveRecord::Migration
def self.up
transactional_loop(Company, :include => :invoicing_profile) do |company|
# do something to or with company
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.