Module: Activerecord::Transactionable::ClassMethods

Defined in:
lib/activerecord/transactionable.rb

Instance Method Summary collapse

Instance Method Details

#transaction_wrapper(object: nil, **args) ⇒ Object

Raises:

  • (ArgumentError)


58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/activerecord/transactionable.rb', line 58

def transaction_wrapper(object: nil, **args)
  lock = args.delete(:lock)
  inside_args = extract_args(args, INSIDE_TRANSACTION_ERROR_HANDLERS)
  outside_args = extract_args(args, OUTSIDE_TRANSACTION_ERROR_HANDLERS)
  transaction_open = ActiveRecord::Base.connection.transaction_open?
  raise ArgumentError, "#{self} does not know how to handle arguments: #{args.keys.inspect}" unless args.keys.empty?
  if ERRORS_TO_DISALLOW_INSIDE_TRANSACTION.detect { |error| inside_args.values.flatten.uniq.include?(error) }
    raise ArgumentError, "#{self} should not rescue #{ERRORS_TO_DISALLOW_INSIDE_TRANSACTION.inspect} inside a transaction: #{inside_args.keys.inspect}"
  end
  transaction_args = extract_args(args, TRANSACTION_METHOD_ARG_NAMES)
  if transaction_open
    unless transaction_args[REQUIRES_NEW]
      transaction_args[REQUIRES_NEW] = true
      logger.warn("[#{self}.transaction_wrapper] Opening a nested transaction. Setting require_new: true")
    else
      logger.debug("[#{self}.transaction_wrapper] Will start a nested transaction.")
    end
  end
  error_handler_outside_transaction(object: object, transaction_open: transaction_open, **outside_args) do |outside_is_retry|
    run_inside_transaction_block(transaction_args: transaction_args, inside_args: inside_args, lock: lock, transaction_open: transaction_open, object: object) do |is_retry|
      # regardless of the retry being inside or outside the transaction, it is still a retry.
      yield outside_is_retry || is_retry
    end
  end
end