Full Code of grosser/test_after_commit for AI

master a3cbb3624b0e cached
17 files
19.6 KB
5.6k tokens
37 symbols
1 requests
Download .txt
Repository: grosser/test_after_commit
Branch: master
Commit: a3cbb3624b0e
Files: 17
Total size: 19.6 KB

Directory structure:
gitextract_de18ncmi/

├── .travis.yml
├── Gemfile
├── MIT-LICENSE
├── Rakefile
├── Readme.md
├── gemfiles/
│   ├── 32.gemfile
│   ├── 40.gemfile
│   ├── 41.gemfile
│   └── 42.gemfile
├── lib/
│   ├── test_after_commit/
│   │   ├── database_statements.rb
│   │   ├── version.rb
│   │   └── with_transaction_state.rb
│   └── test_after_commit.rb
├── spec/
│   ├── database.rb
│   ├── spec_helper.rb
│   └── test_after_commit_spec.rb
└── test_after_commit.gemspec

================================================
FILE CONTENTS
================================================

================================================
FILE: .travis.yml
================================================
language: ruby
sudo: false
cache: bundler
bundler_args: '--path vendor/bundle'
gemfile:
  - gemfiles/32.gemfile
  - gemfiles/40.gemfile
  - gemfiles/41.gemfile
  - gemfiles/42.gemfile
rvm:
  - 2.0.0
  - 2.1.8
  - 2.2.4
env:
  - REAL=1
  - TEST=1
script: bundle exec rake spec


================================================
FILE: Gemfile
================================================
source "https://rubygems.org"
gemspec

gem 'rails-observers'


================================================
FILE: MIT-LICENSE
================================================
Copyright (c) 2014 Michael Grosser <michael@grosser.it>

MIT License

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


================================================
FILE: Rakefile
================================================
require 'bundler/setup'
require 'bundler/gem_tasks'
require 'bump/tasks'
require 'wwtd/tasks'

task :spec do
  sh "rspec spec/"
end

task :default => "wwtd:local"


================================================
FILE: Readme.md
================================================
Make after_commit callbacks fire in tests for Rails 3+ with transactional_fixtures = true.

**Deprecation** this is no longer needed on rails 5.0+ https://github.com/rails/rails/pull/18458

Install
=======

    gem install test_after_commit

    # Gemfile (never include in :development !)
    gem 'test_after_commit', :group => :test

Usage
=====
Test that the methods get called or the side-effect of the methods, something like:

```Ruby
class Car < ActiveRecord::Base
  after_commit :foo, :on => :update

  def foo
    $foo = 1
  end
end

...

it "sets $foo on commit" do
  $foo.should == nil
  car.save!
  $foo.should == 1
end
```

### Temporary disable after commit hooks

In your test_helper, you can specify the default

```
TestAfterCommit.enabled = true
```

Then use blocks in your tests to change the behavior:

```
TestAfterCommit.with_commits(true) do
  my_tests
end

TestAfterCommit.with_commits(false) do
  my_tests
end
```

TIPS
====
 - hooks do not re-raise errors (with or without this gem) use [after_commit_exception_notification](https://github.com/grosser/after_commit_exception_notification)

Author
======

Inspired by https://gist.github.com/1305285

### [Contributors](https://github.com/grosser/test_after_commit/contributors)
 - [James Le Cuirot](https://github.com/chewi)
 - [emirose](https://github.com/emirose)
 - [Brad Gessler](https://github.com/bradgessler)
 - [Rohan McGovern](https://github.com/rohanpm)
 - [lsylvester](https://github.com/lsylvester)
 - [Tony Novak](https://github.com/afn)
 - [Brian Palmer](https://github.com/codekitchen)
 - [Oleg Dashevskii](https://github.com/be9)
 - [Jonathan Spies](https://github.com/jspies)
 - [Nick Sieger](https://github.com/nicksieger)

[Michael Grosser](http://grosser.it)<br/>
michael@grosser.it<br/>
License: MIT<br/>
[![Build Status](https://travis-ci.org/grosser/test_after_commit.png)](https://travis-ci.org/grosser/test_after_commit)


================================================
FILE: gemfiles/32.gemfile
================================================
source "https://rubygems.org"

gemspec :path=>"../"

gem "activerecord", "~> 3.2.18"
gem "i18n", "~> 0.6.9" # 0.7 does not support 1.9
gem "bump", "0.5.2" # after that it's 1.9.3 only


================================================
FILE: gemfiles/40.gemfile
================================================
source "https://rubygems.org"

gemspec :path=>"../"

gem "activerecord", "~> 4.0.6"
gem "rails-observers"


================================================
FILE: gemfiles/41.gemfile
================================================
source "https://rubygems.org"

gemspec :path=>"../"

gem "activerecord", "~> 4.1.2"
gem "rails-observers"


================================================
FILE: gemfiles/42.gemfile
================================================
source "https://rubygems.org"

gemspec :path=>"../"

gem "activerecord", "~> 4.2.0.beta1"
gem "rails-observers"


================================================
FILE: lib/test_after_commit/database_statements.rb
================================================
module TestAfterCommit::DatabaseStatements
  def transaction(*)
    @test_open_transactions ||= 0
    skip_emulation = ActiveRecord::Base.connection.open_transactions.zero?
    run_callbacks = false
    result = nil
    rolled_back = false

    super do
      begin
        @test_open_transactions += 1
        if ActiveRecord::VERSION::MAJOR == 3
          @_current_transaction_records.push([]) if @_current_transaction_records.empty?
        end
        result = yield
      rescue Exception
        rolled_back = true
        raise
      ensure
        @test_open_transactions -= 1
        if @test_open_transactions == 0 && !rolled_back && !skip_emulation
          if TestAfterCommit.enabled
            run_callbacks = true
          elsif ActiveRecord::VERSION::MAJOR == 3
            @_current_transaction_records.clear
          end
        end
      end
    end
  ensure
    test_commit_records if run_callbacks
    result
  end

  def test_commit_records
    if ActiveRecord::VERSION::MAJOR == 3
      commit_transaction_records
    else
      # To avoid an infinite loop, we need to copy the transaction locally, and clear out
      # `records` on the copy that stays in the AR stack. Otherwise new
      # transactions inside a commit callback will cause an infinite loop.
      #
      # This is because we're re-using the transaction on the stack, before
      # it's been popped off and re-created by the AR code.
      original = @transaction || @transaction_manager.current_transaction

      return unless original.respond_to?(:records)

      transaction = original.dup
      transaction.instance_variable_set(:@records, transaction.records.dup) # deep clone of records array
      original.records.clear                                                # so that this clear doesn't clear out both copies
      transaction.commit_records
    end
  end
end


================================================
FILE: lib/test_after_commit/version.rb
================================================
module TestAfterCommit
  VERSION = '1.2.2'
end


================================================
FILE: lib/test_after_commit/with_transaction_state.rb
================================================
# disable parts of the sync code that starts looping
module TestAfterCommit
  module WithTransactionState
    def sync_with_transaction_state
      @reflects_state ||= []
      @reflects_state[0] = true
      super
    end
  end
end


================================================
FILE: lib/test_after_commit.rb
================================================
require 'test_after_commit/version'

if ActiveRecord::VERSION::MAJOR >= 5
  raise 'after_commit testing is baked into rails 5, you no longer need test_after_commit gem'
end

if ActiveRecord::VERSION::MAJOR >= 4
  require 'test_after_commit/with_transaction_state'
  ActiveRecord::Base.send(:prepend, TestAfterCommit::WithTransactionState)
end

require 'test_after_commit/database_statements'
ActiveRecord::ConnectionAdapters::AbstractAdapter.send(:prepend, TestAfterCommit::DatabaseStatements)

module TestAfterCommit
  @enabled = true
  class << self
    attr_accessor :enabled

    def with_commits(value = true)
      old = enabled
      self.enabled = value
      yield
    ensure
      self.enabled = old
    end
  end
end


================================================
FILE: spec/database.rb
================================================
# setup database
require 'active_record'

if ActiveRecord::VERSION::MAJOR > 3
  require "rails/observers/activerecord/active_record"
end

if ActiveRecord::VERSION::STRING >= "4.2.0"
  ActiveRecord::Base.raise_in_transactional_callbacks = true
end

ActiveRecord::Base.establish_connection(
  :adapter  => 'sqlite3',
  :database => ':memory:'
)

ActiveRecord::Migration.verbose = false

ActiveRecord::Schema.define(:version => 1) do
  create_table "cars", :force => true do |t|
    t.integer :counter, :default => 0, :null => false
    t.integer :car_id
    t.timestamps :null => false
  end

  create_table "addresses", :force => true do |t|
    t.integer :number_of_residents, :default => 0, :null => false
    t.timestamps :null => false
  end

  create_table "people", :force => true do |t|
    t.belongs_to :address
    t.timestamps :null => false
  end

  create_table "fu_bears", :force => true do |t|
    t.string :name
    t.timestamps :null => false
  end
end

module Called
  def called(x=nil)
    @called ||= []
    if x
      @called << x
    else
      @called
    end
  end
end

class Car < ActiveRecord::Base
  extend Called

  has_many :cars

  after_commit :simple_after_commit
  after_commit :simple_after_commit_on_create, :on => :create
  after_commit :save_once, :on => :create, :if => :do_after_create_save
  after_commit :simple_after_commit_on_update, :on => :update
  after_commit :maybe_raise_errors
  after_commit :save_open_transactions_count

  after_save :trigger_rollback

  attr_accessor :make_rollback, :raise_error, :do_after_create_save

  def trigger_rollback
    raise ActiveRecord::Rollback if make_rollback
  end

  def self.returning_method_with_transaction
    Car.transaction do
      return Car.create
    end
  end

  attr_reader :open_transactions

  private

  def save_open_transactions_count
    @open_transactions = ActiveRecord::Base.connection.open_transactions
  end

  def save_once
    update_attributes(:counter => 3) unless counter == 3
    self.class.called :save_once
  end

  def maybe_raise_errors
    if raise_error
      # puts "MAYBE RAISE" # just debugging, but it really does not work ...
      raise "Expected error"
    end
  end

  def simple_after_commit
    self.class.called :always
  end

  def simple_after_commit_on_create
    self.class.called :create
  end

  def simple_after_commit_on_update
    self.class.called :update
  end
end

class CarObserver < ActiveRecord::Observer
  cattr_accessor :recording
  cattr_accessor :callback

  [:after_commit, :after_rollback].each do |action|
    define_method action do |record|
      return unless recording
      Car.called << "observed_#{action}".to_sym
      Untracked.create!
      callback.call() if callback
    end
  end
end

Car.observers = :car_observer
Car.instantiate_observers

class Bar < ActiveRecord::Base
  self.table_name = "cars"
  has_many :bars, :foreign_key => :car_id
end

class MultiBar < ActiveRecord::Base
  extend Called

  self.table_name = "cars"

  after_commit :one, :on => :create
  after_commit :two, :on => :create

  def one
    self.class.called << :one
  end

  def two
    self.class.called << :two
  end
end

class Address < ActiveRecord::Base
  has_many :people

  after_commit :create_residents, :on => :create

  def create_residents
    if ActiveRecord::VERSION::MAJOR == 3
      # stupid hack because nested after_commit is broken on rails 3 and loops
      return if @create_residents
      @create_residents = true
    end

    Person.create!(:address => self)
    Person.create!(:address => self)
  end
end

class Person < ActiveRecord::Base
  belongs_to :address

  after_commit :update_number_of_residents_on_address, :on => :create

  def update_number_of_residents_on_address
    address.update_attributes(:number_of_residents => address.number_of_residents + 1)
  end
end

class Untracked < ActiveRecord::Base
  self.table_name = "cars"
end

class FuBear < ActiveRecord::Base
  extend Called

  self.table_name = "fu_bears"
  validates_presence_of :name

  after_commit :simple_after_commit

  def simple_after_commit
    self.class.called :always
  end
end


================================================
FILE: spec/spec_helper.rb
================================================
require 'bundler/setup'
require File.expand_path '../database', __FILE__
I18n.enforce_available_locales = false

def rails3?
  ActiveRecord::VERSION::MAJOR == 3
end

def rails4?
  ActiveRecord::VERSION::MAJOR >= 4
end

def rails42?
  rails4? && ActiveRecord::VERSION::MINOR >= 2
end

require 'test_after_commit'
if ENV['REAL']
  puts 'using real transactions'
  TestAfterCommit.enabled = false
end

module ConnectionFinder
  def connection
    @connection ||=
      if rails4?
        ActiveRecord::Base.connection_handler.connection_pool_list.map(&:connection).first
      else
        ActiveRecord::Base.connection_handler.connection_pools.values.map(&:connection).first
      end
  end
end

RSpec.configure do |config|
  config.include ConnectionFinder

  unless ENV['REAL']
    config.around do |example|
      # open a transaction without using .transaction as activerecord use_transactional_fixtures does
      if ActiveRecord::VERSION::MAJOR > 3
        connection.begin_transaction :joinable => false
      else
        connection.increment_open_transactions
        connection.transaction_joinable = false
        connection.begin_db_transaction
      end

      example.call

      connection.rollback_db_transaction
      if ActiveRecord::VERSION::MAJOR == 3
        connection.decrement_open_transactions
      end
    end
  end

  config.expect_with(:rspec) { |c| c.syntax = :should }
  config.mock_with(:rspec) { |c| c.syntax = :should }
end


================================================
FILE: spec/test_after_commit_spec.rb
================================================
require 'spec_helper'

describe TestAfterCommit do
  before do
    CarObserver.recording = false
    Car.called.clear
  end

  after do
    TestAfterCommit.enabled = true unless ENV["REAL"]
  end

  it "has a VERSION" do
    TestAfterCommit::VERSION.should =~ /^[\.\da-z]+$/
  end

  it "fires on create" do
    Car.create
    Car.called.should == [:create, :always]
  end

  it "runs callback outside of transaction" do
    car = Car.create
    car.open_transactions.should == ActiveRecord::Base.connection.open_transactions
  end

  it "works outside of transaction" do
    car = described_class.with_commits(true) { Car.create }
    car.destroy
  end if ENV["REAL"]

  it "fires on update" do
    car = Car.create
    Car.called.clear
    car.save!
    Car.called.should == [:update, :always]
  end

  it "fires on update_attribute" do
    car = Car.create
    Car.called.clear
    car.update_attribute :counter, 123
    Car.called.should == [:update, :always]
  end

  it "does not fire on rollback" do
    car = Car.new
    car.make_rollback = true
    car.save.should == nil
    Car.called.should == []
  end

  it "does not fire on ActiveRecord::RecordInvalid" do
    lambda {
      FuBear.create!
    }.should raise_exception(ActiveRecord::RecordInvalid)
    FuBear.called.should == []
  end

  it "does not fire multiple times in nested transactions" do
    Car.transaction do
      Car.transaction do
        Car.create!
        Car.called.should == []
      end
      Car.called.should == []
    end
    Car.called.should == [:create, :always]
  end

  it "fires when transaction block returns from method" do
    Car.returning_method_with_transaction
    Car.called.should == [:create, :always]
  end

  if rails42?
    it "raises errors" do
      car = Car.new
      car.raise_error = true
      lambda { car.save! }.should raise_error(RuntimeError)
    end
  else
    it "does not raises errors" do
      car = Car.new
      car.raise_error = true
      car.save!
    end
  end

  if rails42?
    context "with config.active_record.raise_in_transactional_callbacks" do
      around do |test|
        old = ActiveRecord::Base.raise_in_transactional_callbacks
        ActiveRecord::Base.raise_in_transactional_callbacks = true
        begin
          test.call
        ensure
          ActiveRecord::Base.raise_in_transactional_callbacks = old
        end
      end

      it "keeps working after an exception is raised" do
        car = Car.new
        car.raise_error = true
        lambda { car.save! }.should raise_error(RuntimeError)

        car = Car.new
        car.save!
        Car.called.should include(:always)
      end
    end
  end

  it "can do 1 save in after_commit" do
    car = Car.new
    car.do_after_create_save = true
    car.save!

    expected = if rails4?
      [:save_once, :create, :always, :save_once, :always]
    else
      [:save_once, :create, :always, :save_once, :create, :always]
    end
    Car.called.should == expected
    car.counter.should == 3
  end

  it "returns on create and on create of associations" do
    Car.create!.class.should == Car
    Car.create!.cars.create.class.should == Car unless rails4?
  end

  it "returns on create and on create of associations without after_commit" do
    Bar.create!.class.should == Bar
    Bar.create!.bars.create.class.should == Bar unless rails4?
  end

  it "calls callbacks in correct order" do
    MultiBar.create!
    MultiBar.called.should == [:two, :one]
  end

  context "Observer" do
    before do
      CarObserver.recording = true
    end

    it "should record commits" do
      Car.transaction do
        Car.create
      end
      Car.called.should == [:observed_after_commit, :create, :always]
    end

    it "should record rollbacks caused by ActiveRecord::Rollback" do
      Car.transaction do
        Car.create
        raise ActiveRecord::Rollback
      end
      Car.called.should == [:observed_after_rollback]
    end

    it "should record rollbacks caused by any type of exception" do
      begin
        Car.transaction do
          car = Car.create
          raise Exception, 'simulated error'
        end
      rescue Exception => e
        e.message.should == 'simulated error'
      end
      Car.called.should == [:observed_after_rollback]
    end

    it "should see the correct number of open transactions during callbacks" do
      skip if ENV["REAL"]
      begin
        open_txn = nil
        CarObserver.callback = proc { open_txn = Car.connection.instance_variable_get(:@test_open_transactions) }
        Car.transaction do
          Car.create
        end
        open_txn.should == 0
      ensure
        CarObserver.callback = nil
      end
    end
  end

  context "block behavior" do
    it "does not fire if turned off" do
      TestAfterCommit.enabled = false
      Car.create
      Car.called.should == []
    end

    it "always fires with when enabled by a block" do
      TestAfterCommit.enabled = false
      TestAfterCommit.with_commits(true) do
        Car.create
        Car.called.should == [:create, :always]
      end
    end

    it "defaults to with commits" do
      TestAfterCommit.with_commits do
        Car.create
        Car.called.should == [:create, :always]
      end
    end

    it "does not fire with without commits" do
      TestAfterCommit.with_commits(false) do
        Car.create
        Car.called.should == []
      end
    end
  end unless ENV["REAL"]

  context "nested after_commit" do
    it 'is executed' do
      skip if rails4? # infinite loop in REAL and fails in TEST and lots of noise when left as pending

      @address = Address.create!
      lambda {
        Person.create!(:address => @address)
      }.should change(@address, :number_of_residents).by(1)

      # one from the line above and two from the after_commit
      @address.people.count.should == 3

      @address.number_of_residents.should == 3
    end
  end
end

if rails3? && !ENV["REAL"]
  describe TestAfterCommit, "with mixed TAC enabled specs" do
    before do
      TestAfterCommit.enabled = false
      Car.called.clear
    end

    context "and a test with TAC disabled" do
      it "creates a record" do
        Car.new.save!
        Car.called.should == []
      end

      it "verifies that records are empty before each test 1" do
        connection.instance_variable_get(:@_current_transaction_records).should be_empty
      end
    end

    context "and a test with TAC enabled" do
      before { TestAfterCommit.enabled = true }

      it "creates a record and fires commit callbacks" do
        Car.new.save!
        Car.called.should == [:create, :always]
      end

      it "verifies that records are empty before each test 2" do
        connection.instance_variable_get(:@_current_transaction_records).should be_empty
      end
    end
  end
end


================================================
FILE: test_after_commit.gemspec
================================================
name = "test_after_commit"
require "./lib/#{name}/version"

Gem::Specification.new name, TestAfterCommit::VERSION do |s|
  s.summary = "makes after_commit callbacks testable in Rails 3+ with transactional_fixtures"
  s.authors = ["Michael Grosser"]
  s.email = "michael@grosser.it"
  s.homepage = "https://github.com/grosser/#{name}"
  s.files = `git ls-files lib Readme.md MIT-LICENSE`.split("\n")
  s.license = 'MIT'

  s.required_ruby_version = '>= 2.0.0'
  s.add_runtime_dependency "activerecord", [">= 3.2", "< 5.0"]
  
  s.add_development_dependency "wwtd"
  s.add_development_dependency "bump"
  s.add_development_dependency "rake"
  s.add_development_dependency "sqlite3"
  s.add_development_dependency "rspec"
end
Download .txt
gitextract_de18ncmi/

├── .travis.yml
├── Gemfile
├── MIT-LICENSE
├── Rakefile
├── Readme.md
├── gemfiles/
│   ├── 32.gemfile
│   ├── 40.gemfile
│   ├── 41.gemfile
│   └── 42.gemfile
├── lib/
│   ├── test_after_commit/
│   │   ├── database_statements.rb
│   │   ├── version.rb
│   │   └── with_transaction_state.rb
│   └── test_after_commit.rb
├── spec/
│   ├── database.rb
│   ├── spec_helper.rb
│   └── test_after_commit_spec.rb
└── test_after_commit.gemspec
Download .txt
SYMBOL INDEX (37 symbols across 6 files)

FILE: lib/test_after_commit.rb
  type TestAfterCommit (line 15) | module TestAfterCommit
    function with_commits (line 20) | def with_commits(value = true)

FILE: lib/test_after_commit/database_statements.rb
  type TestAfterCommit::DatabaseStatements (line 1) | module TestAfterCommit::DatabaseStatements
    function transaction (line 2) | def transaction(*)
    function test_commit_records (line 35) | def test_commit_records

FILE: lib/test_after_commit/version.rb
  type TestAfterCommit (line 1) | module TestAfterCommit

FILE: lib/test_after_commit/with_transaction_state.rb
  type TestAfterCommit (line 2) | module TestAfterCommit
    type WithTransactionState (line 3) | module WithTransactionState
      function sync_with_transaction_state (line 4) | def sync_with_transaction_state

FILE: spec/database.rb
  type Called (line 42) | module Called
    function called (line 43) | def called(x=nil)
  class Car (line 53) | class Car < ActiveRecord::Base
    method trigger_rollback (line 69) | def trigger_rollback
    method returning_method_with_transaction (line 73) | def self.returning_method_with_transaction
    method save_open_transactions_count (line 83) | def save_open_transactions_count
    method save_once (line 87) | def save_once
    method maybe_raise_errors (line 92) | def maybe_raise_errors
    method simple_after_commit (line 99) | def simple_after_commit
    method simple_after_commit_on_create (line 103) | def simple_after_commit_on_create
    method simple_after_commit_on_update (line 107) | def simple_after_commit_on_update
  class CarObserver (line 112) | class CarObserver < ActiveRecord::Observer
  class Bar (line 129) | class Bar < ActiveRecord::Base
  class MultiBar (line 134) | class MultiBar < ActiveRecord::Base
    method one (line 142) | def one
    method two (line 146) | def two
  class Address (line 151) | class Address < ActiveRecord::Base
    method create_residents (line 156) | def create_residents
  class Person (line 168) | class Person < ActiveRecord::Base
    method update_number_of_residents_on_address (line 173) | def update_number_of_residents_on_address
  class Untracked (line 178) | class Untracked < ActiveRecord::Base
  class FuBear (line 182) | class FuBear < ActiveRecord::Base
    method simple_after_commit (line 190) | def simple_after_commit

FILE: spec/spec_helper.rb
  function rails3? (line 5) | def rails3?
  function rails4? (line 9) | def rails4?
  function rails42? (line 13) | def rails42?
  type ConnectionFinder (line 23) | module ConnectionFinder
    function connection (line 24) | def connection
Condensed preview — 17 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (22K chars).
[
  {
    "path": ".travis.yml",
    "chars": 276,
    "preview": "language: ruby\nsudo: false\ncache: bundler\nbundler_args: '--path vendor/bundle'\ngemfile:\n  - gemfiles/32.gemfile\n  - gemf"
  },
  {
    "path": "Gemfile",
    "chars": 61,
    "preview": "source \"https://rubygems.org\"\ngemspec\n\ngem 'rails-observers'\n"
  },
  {
    "path": "MIT-LICENSE",
    "chars": 1093,
    "preview": "Copyright (c) 2014 Michael Grosser <michael@grosser.it>\n\nMIT License\n\nPermission is hereby granted, free of charge, to a"
  },
  {
    "path": "Rakefile",
    "chars": 163,
    "preview": "require 'bundler/setup'\nrequire 'bundler/gem_tasks'\nrequire 'bump/tasks'\nrequire 'wwtd/tasks'\n\ntask :spec do\n  sh \"rspec"
  },
  {
    "path": "Readme.md",
    "chars": 1923,
    "preview": "Make after_commit callbacks fire in tests for Rails 3+ with transactional_fixtures = true.\n\n**Deprecation** this is no l"
  },
  {
    "path": "gemfiles/32.gemfile",
    "chars": 184,
    "preview": "source \"https://rubygems.org\"\n\ngemspec :path=>\"../\"\n\ngem \"activerecord\", \"~> 3.2.18\"\ngem \"i18n\", \"~> 0.6.9\" # 0.7 does n"
  },
  {
    "path": "gemfiles/40.gemfile",
    "chars": 106,
    "preview": "source \"https://rubygems.org\"\n\ngemspec :path=>\"../\"\n\ngem \"activerecord\", \"~> 4.0.6\"\ngem \"rails-observers\"\n"
  },
  {
    "path": "gemfiles/41.gemfile",
    "chars": 106,
    "preview": "source \"https://rubygems.org\"\n\ngemspec :path=>\"../\"\n\ngem \"activerecord\", \"~> 4.1.2\"\ngem \"rails-observers\"\n"
  },
  {
    "path": "gemfiles/42.gemfile",
    "chars": 112,
    "preview": "source \"https://rubygems.org\"\n\ngemspec :path=>\"../\"\n\ngem \"activerecord\", \"~> 4.2.0.beta1\"\ngem \"rails-observers\"\n"
  },
  {
    "path": "lib/test_after_commit/database_statements.rb",
    "chars": 1875,
    "preview": "module TestAfterCommit::DatabaseStatements\n  def transaction(*)\n    @test_open_transactions ||= 0\n    skip_emulation = A"
  },
  {
    "path": "lib/test_after_commit/version.rb",
    "chars": 47,
    "preview": "module TestAfterCommit\n  VERSION = '1.2.2'\nend\n"
  },
  {
    "path": "lib/test_after_commit/with_transaction_state.rb",
    "chars": 233,
    "preview": "# disable parts of the sync code that starts looping\nmodule TestAfterCommit\n  module WithTransactionState\n    def sync_w"
  },
  {
    "path": "lib/test_after_commit.rb",
    "chars": 728,
    "preview": "require 'test_after_commit/version'\n\nif ActiveRecord::VERSION::MAJOR >= 5\n  raise 'after_commit testing is baked into ra"
  },
  {
    "path": "spec/database.rb",
    "chars": 4129,
    "preview": "# setup database\nrequire 'active_record'\n\nif ActiveRecord::VERSION::MAJOR > 3\n  require \"rails/observers/activerecord/ac"
  },
  {
    "path": "spec/spec_helper.rb",
    "chars": 1456,
    "preview": "require 'bundler/setup'\nrequire File.expand_path '../database', __FILE__\nI18n.enforce_available_locales = false\n\ndef rai"
  },
  {
    "path": "spec/test_after_commit_spec.rb",
    "chars": 6819,
    "preview": "require 'spec_helper'\n\ndescribe TestAfterCommit do\n  before do\n    CarObserver.recording = false\n    Car.called.clear\n  "
  },
  {
    "path": "test_after_commit.gemspec",
    "chars": 723,
    "preview": "name = \"test_after_commit\"\nrequire \"./lib/#{name}/version\"\n\nGem::Specification.new name, TestAfterCommit::VERSION do |s|"
  }
]

About this extraction

This page contains the full source code of the grosser/test_after_commit GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 17 files (19.6 KB), approximately 5.6k tokens, and a symbol index with 37 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!