Class: ActiveRecord::ConnectionAdapters::Transaction
    Do not use.  This class is for internal use only.
  
| Relationships & Source Files | |
| Namespace Children | |
| 
       Classes: 
      
     | |
| Extension / Inclusion / Inheritance Descendants | |
| 
         Subclasses: 
        
       | 
    |
| Inherits: | Object | 
| Defined in: | activerecord/lib/active_record/connection_adapters/abstract/transaction.rb | 
Class Method Summary
Instance Attribute Summary
- #closed? ⇒ Boolean readonly
 - #connection readonly
 - #dirty? ⇒ Boolean readonly
 - #full_rollback? ⇒ Boolean readonly
 - #isolation_level readonly
 - #joinable? ⇒ Boolean readonly
 - #materialized? ⇒ Boolean readonly
 - #open? ⇒ Boolean readonly
 - 
    
      #restartable?  ⇒ Boolean 
    
    readonly
    
Can this transaction’s current state be recreated by rollback+begin ?
 - #savepoint_name readonly
 - #state readonly
 - #user_transaction readonly
 - #written rw
 
Instance Method Summary
- #add_record(record, ensure_finalize = true)
 - #after_commit(&block)
 - #after_rollback(&block)
 - #before_commit(&block)
 - #before_commit_records
 - #commit_records
 - #dirty!
 - #incomplete!
 - #invalidate!
 - #invalidated? ⇒ Boolean
 - #materialize!
 - #records
 - #restore!
 - #rollback_records
 - #append_callbacks(callbacks) protected
 - #prepare_instances_to_run_callbacks_on(records) private
 - #run_action_on_records(records, instances_to_run_callbacks_on) private
 - #unique_records private
 
Constructor Details
    .new(connection, isolation: nil, joinable: true, run_commit_callbacks: false)  ⇒ Transaction 
  
# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 153
def initialize(connection, isolation: nil, joinable: true, run_commit_callbacks: false) super() @connection = connection @state = TransactionState.new @callbacks = nil @records = nil @isolation_level = isolation @materialized = false @joinable = joinable @run_commit_callbacks = run_commit_callbacks @lazy_enrollment_records = nil @dirty = false @user_transaction = joinable ? ActiveRecord::Transaction.new(self) : ActiveRecord::Transaction::NULL_TRANSACTION @instrumenter = TransactionInstrumenter.new(connection: connection, transaction: @user_transaction) end
Instance Attribute Details
    #closed?  ⇒ Boolean  (readonly)
  
  [ GitHub ]
# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 181
def closed? false end
#connection (readonly)
[ GitHub ]# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 148
attr_reader :connection, :state, :savepoint_name, :isolation_level, :user_transaction
    #dirty?  ⇒ Boolean  (readonly)
  
  [ GitHub ]
# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 173
def dirty? @dirty end
    #full_rollback?  ⇒ Boolean  (readonly)
  
  [ GitHub ]
# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 327
def full_rollback?; true; end
#isolation_level (readonly)
[ GitHub ]# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 148
attr_reader :connection, :state, :savepoint_name, :isolation_level, :user_transaction
    #joinable?  ⇒ Boolean  (readonly)
  
  [ GitHub ]
# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 328
def joinable?; @joinable; end
    #materialized?  ⇒ Boolean  (readonly)
  
  [ GitHub ]
# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 242
def materialized? @materialized end
    #open?  ⇒ Boolean  (readonly)
  
  [ GitHub ]
# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 177
def open? true end
    #restartable?  ⇒ Boolean  (readonly)
  
Can this transaction’s current state be recreated by rollback+begin ?
#savepoint_name (readonly)
[ GitHub ]# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 148
attr_reader :connection, :state, :savepoint_name, :isolation_level, :user_transaction
#state (readonly)
[ GitHub ]# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 148
attr_reader :connection, :state, :savepoint_name, :isolation_level, :user_transaction
#user_transaction (readonly)
[ GitHub ]# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 148
attr_reader :connection, :state, :savepoint_name, :isolation_level, :user_transaction
#written (rw)
[ GitHub ]# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 149
attr_accessor :written
Instance Method Details
#add_record(record, ensure_finalize = true)
[ GitHub ]# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 185
def add_record(record, ensure_finalize = true) @records ||= [] if ensure_finalize @records << record else @lazy_enrollment_records ||= ObjectSpace::WeakMap.new @lazy_enrollment_records[record] = record end end
#after_commit(&block)
[ GitHub ]# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 203
def after_commit(&block) if @state.finalized? raise ActiveRecordError, "Cannot register callbacks on a finalized transaction" end (@callbacks ||= []) << Callback.new(:after_commit, block) end
#after_rollback(&block)
[ GitHub ]# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 211
def after_rollback(&block) if @state.finalized? raise ActiveRecordError, "Cannot register callbacks on a finalized transaction" end (@callbacks ||= []) << Callback.new(:after_rollback, block) end
#append_callbacks(callbacks) (protected)
[ GitHub ]# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 331
def append_callbacks(callbacks) # :nodoc: (@callbacks ||= []).concat(callbacks) end
#before_commit(&block)
[ GitHub ]# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 195
def before_commit(&block) if @state.finalized? raise ActiveRecordError, "Cannot register callbacks on a finalized transaction" end (@callbacks ||= []) << Callback.new(:before_commit, block) end
#before_commit_records
[ GitHub ]# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 274
def before_commit_records if @run_commit_callbacks if records if ActiveRecord.before_committed_on_all_records ite = unique_records instances_to_run_callbacks_on = records.each_with_object({}) do |record, candidates| candidates[record] = record end run_action_on_records(ite, instances_to_run_callbacks_on) do |record, should_run_callbacks| record.before_committed! if should_run_callbacks end else records.uniq.each(&:before_committed!) end end @callbacks&.each(&:before_commit) end # Note: When @run_commit_callbacks is false #commit_records takes care of appending # remaining callbacks to the parent transaction end
#commit_records
[ GitHub ]# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 298
def commit_records if records begin ite = unique_records if @run_commit_callbacks instances_to_run_callbacks_on = prepare_instances_to_run_callbacks_on(ite) run_action_on_records(ite, instances_to_run_callbacks_on) do |record, should_run_callbacks| record.committed!(should_run_callbacks: should_run_callbacks) end else while record = ite.shift # if not running callbacks, only adds the record to the parent transaction connection.add_transaction_record(record) end end ensure ite&.each { |i| i.committed!(should_run_callbacks: false) } end end if @run_commit_callbacks @callbacks&.each(&:after_commit) elsif @callbacks connection.current_transaction.append_callbacks(@callbacks) end end
#dirty!
[ GitHub ]# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 169
def dirty! @dirty = true end
#incomplete!
[ GitHub ]# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 233
def incomplete! @instrumenter.finish(:incomplete) if materialized? end
#invalidate!
[ GitHub ]# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 151
delegate :invalidate!, :invalidated?, to: :@state
    #invalidated?  ⇒ Boolean 
  
# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 151
delegate :invalidate!, :invalidated?, to: :@state
#materialize!
[ GitHub ]# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 237
def materialize! @materialized = true @instrumenter.start end
#prepare_instances_to_run_callbacks_on(records) (private)
[ GitHub ]# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 348
def prepare_instances_to_run_callbacks_on(records) records.each_with_object({}) do |record, candidates| next unless record.trigger_transactional_callbacks? earlier_saved_candidate = candidates[record] next if earlier_saved_candidate && record.class.run_commit_callbacks_on_first_saved_instances_in_transaction # If the candidate instance destroyed itself in the database, then # instances which were added to the transaction afterwards, and which # think they updated themselves, are wrong. They should not replace # our candidate as an instance to run callbacks on next if earlier_saved_candidate&.destroyed? && !record.destroyed? # If the candidate instance was created inside of this transaction, # then instances which were subsequently loaded from the database # and updated need that state transferred to them so that # the after_create_commit callbacks are run record._new_record_before_last_commit = true if earlier_saved_candidate&._new_record_before_last_commit # The last instance to save itself is likeliest to have internal # state that matches what's committed to the database candidates[record] = record end end
#records
[ GitHub ]# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 219
def records if @lazy_enrollment_records @records.concat @lazy_enrollment_records.values @lazy_enrollment_records = nil end @records end
#restore!
[ GitHub ]# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 246
def restore! if materialized? incomplete! @materialized = false materialize! end end
#rollback_records
[ GitHub ]# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 254
def rollback_records if records begin ite = unique_records instances_to_run_callbacks_on = prepare_instances_to_run_callbacks_on(ite) run_action_on_records(ite, instances_to_run_callbacks_on) do |record, should_run_callbacks| record.rolledback!(force_restore_state: full_rollback?, should_run_callbacks: should_run_callbacks) end ensure ite&.each do |i| i.rolledback!(force_restore_state: full_rollback?, should_run_callbacks: false) end end end @callbacks&.each(&:after_rollback) end
#run_action_on_records(records, instances_to_run_callbacks_on) (private)
[ GitHub ]# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 340
def run_action_on_records(records, instances_to_run_callbacks_on) while record = records.shift should_run_callbacks = record.__id__ == instances_to_run_callbacks_on[record].__id__ yield record, should_run_callbacks end end
#unique_records (private)
[ GitHub ]# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 336
def unique_records records.uniq(&:__id__) end