Module: Activerecord::Transactionable::ClassMethods

Defined in:
lib/activerecord/transactionable.rb

Instance Method Summary collapse

Instance Method Details

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



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/activerecord/transactionable.rb', line 62

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?
  unless args.keys.empty?
    raise ArgumentError,
          "#{self} does not know how to handle arguments: #{args.keys.inspect}"
  end
  if ERRORS_TO_DISALLOW_INSIDE_TRANSACTION.detect do |error|
       inside_args.values.flatten.uniq.include?(error)
     end
    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
    if transaction_args[REQUIRES_NEW]
      logger.debug("[#{self}.transaction_wrapper] Will start a nested transaction.")
    else
      transaction_args[REQUIRES_NEW] = true
      logger.warn("[#{self}.transaction_wrapper] Opening a nested transaction. Setting require_new: true")
    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