Repository: rails/rails
File: activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb (Ruby)

Code before:
      # * You are joining an existing open transaction
      # * You are creating a nested (savepoint) transaction
      #
      # The mysql2, trilogy, and postgresql adapters support setting the transaction
      # isolation level.
      #  :args: (requires_new: nil, isolation: nil, &block)
      def transaction(requires_new: nil, isolation: nil, joinable: true, &block)
        if !requires_new && current_transaction.joinable?
          if isolation && current_transaction.isolation != isolation
            raise ActiveRecord::TransactionIsolationError, "cannot set isolation when joining a transaction"
          end
          yield current_transaction.user_transaction
        else
          # If we're running inside the single, non-joinable transaction that
          # ActiveRecord::TestFixtures starts around each example (depth == 1),
          # an `isolation:` hint must be validated then ignored so that the
          # adapter isn't asked to change the isolation level mid-transaction.
          if isolation && open_transactions == 1 && !current_transaction.joinable?
            iso = isolation.to_sym

            unless transaction_isolation_levels.include?(iso)
              raise ActiveRecord::TransactionIsolationError,
                    "invalid transaction isolation level: #{iso.inspect}"
            end

            current_transaction.instance_variable_set(:@isolation_level, iso)
            isolation = nil
          end

          within_new_transaction(isolation: isolation, joinable: joinable, &block)
        end
      rescue ActiveRecord::Rollback
        # rollbacks are silently swallowed
      end

      attr_reader :transaction_manager # :nodoc:

      delegate :within_new_transaction, :open_transactions, :current_transaction, :begin_transaction,
               :commit_transaction, :rollback_transaction, :materialize_transactions,
               :disable_lazy_transactions!, :enable_lazy_transactions!, :dirty_current_transaction,
               to: :transaction_manager

      def mark_transaction_written_if_write(sql) # :nodoc:
        transaction = current_transaction
        if transaction.open?
          transaction.written ||= write_query?(sql)
        end
      end

      def transaction_open?
        current_transaction.open?

Review comment (suggestion):
Happy to introduce `def _set_isolation` on a connection if you think a public method is preferable.

Code after:
      # * You are joining an existing open transaction
      # * You are creating a nested (savepoint) transaction
      #
      # The mysql2, trilogy, and postgresql adapters support setting the transaction
      # isolation level.
      #  :args: (requires_new: nil, isolation: nil, &block)
      def transaction(requires_new: nil, isolation: nil, joinable: true, &block)
        # If we're running inside the single, non-joinable transaction that
        # ActiveRecord::TestFixtures starts around each example (depth == 1),
        # an `isolation:` hint must be validated then ignored so that the
        # adapter isn't asked to change the isolation level mid-transaction.
        if isolation && !requires_new && open_transactions == 1 && !current_transaction.joinable?
          iso = isolation.to_sym

          unless transaction_isolation_levels.include?(iso)
            raise ActiveRecord::TransactionIsolationError,
                  "invalid transaction isolation level: #{iso.inspect}"
          end

          current_transaction.isolation = iso
          isolation = nil
        end

        if !requires_new && current_transaction.joinable?
          if isolation && current_transaction.isolation != isolation
            raise ActiveRecord::TransactionIsolationError, "cannot set isolation when joining a transaction"
          end
          yield current_transaction.user_transaction
        else
          within_new_transaction(isolation: isolation, joinable: joinable, &block)
        end
      rescue ActiveRecord::Rollback
        # rollbacks are silently swallowed
      end

      attr_reader :transaction_manager # :nodoc:

      delegate :within_new_transaction, :open_transactions, :current_transaction, :begin_transaction,
               :commit_transaction, :rollback_transaction, :materialize_transactions,
               :disable_lazy_transactions!, :enable_lazy_transactions!, :dirty_current_transaction,
               to: :transaction_manager

      def mark_transaction_written_if_write(sql) # :nodoc:
        transaction = current_transaction
        if transaction.open?
          transaction.written ||= write_query?(sql)
        end
      end

      def transaction_open?
        current_transaction.open?