neopoly/retryable_record

View on GitHub
lib/retryable_record.rb

Summary

Maintainability
A
55 mins
Test Coverage
require 'active_record'
require 'active_record/base'

# Retries an operation on an ActiveRecord until no StaleObjectError is being raised.
#
# == Example
#
#   class User < ActiveRecord::Base
#     include RetryableRecord
#   end
#
#   user = User.first
#
#   user.retryable do
#     user.username = "foo"
#     user.save!
#   end
#
# == Example using attempts
#
#   class User < ActiveRecord::Base
#     include RetryableRecord
#   end
#
#   user = User.first
#
#   user.retryable(:attempts => 2) do
#     user.username = "foo"
#     user.save!
#   end
#
module RetryableRecord
  # Retryable operations on an ActiveRecord +record+.
  #
  # == Example
  #
  #   RetryableRecord.retry(user) do
  #     user.username = "foo"
  #     user.save!
  #   end
  #
  def retry(record, opts = {})
    attempts = opts[:attempts]
    begin
      yield
    rescue ActiveRecord::StaleObjectError
      unless attempts.nil?
        raise unless attempts > 0
        attempts -= 1
      end
      record.reload
      retry
    end
  end
  module_function :retry

  # Retries operations on an ActiveRecord.
  def retryable(opts = {}, &block)
    RetryableRecord.retry(self, opts, &block)
  end
end