public
Last active

  • Download Gist
migration_transactional_loop.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
# 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
block.call(active_record_instance)
end
page += page + 1
end
break if no_more_records
end
end
end
usage.rb
Ruby
1 2 3 4 5 6 7
class SomeMigration < ActiveRecord::Migration
def self.up
transactional_loop(Company, :include => :invoicing_profile) do |company|
# do something to or with company
end
end
end

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.