15

rspec のトランザクション フィクスチャにより、after_commit が呼び出されなくなりますが、それらを無効にしても

RSpec.configure do |config|
  config.use_transactional_fixtures = false
end

は実行されafter_commit callbackません。

これは、私が問題を作成した最新の rspec / rails を使用した Rails アプリです: git://github.com/sheabarton/after_commit_demo.git

4

5 に答える 5

9

私の場合、database_cleaner の設定を以下に配置して、このような問題を解決しました。

config.use_transactional_fixtures = false

config.before(:suite) do
  DatabaseCleaner.strategy = :deletion
  DatabaseCleaner.clean_with(:truncation)
end

config.before(:each) do
  DatabaseCleaner.start
end

config.after(:each) do
  DatabaseCleaner.clean
end

Rspecでafter_commit/after_transactionをテストしてくれてありがとう

于 2014-05-22T11:59:21.147 に答える
8

これは上記の @jamesdevar の回答に似ていますが、コード ブロックを追加できなかったため、別のエントリを作成する必要があります。

仕様スイート全体の戦略を変更する必要はありません。:transactionグローバルに使用し続け、必要に応じて:deletionor :truncation(両方とも機能) を使用することができます。関連する仕様にフラグを追加するだけです。

config.use_transactional_fixtures = false

config.before(:suite) do
  # The :transaction strategy prevents :after_commit hooks from running
  DatabaseCleaner.strategy = :transaction
  DatabaseCleaner.clean_with(:truncation)
end

config.before(:each, :with_after_commit => true) do
  DatabaseCleaner.strategy = :truncation
end

次に、仕様で:

describe "some test requiring after_commit hooks", :with_after_commit => true do
于 2014-11-10T17:24:42.703 に答える
5

database_cleanerを使用している場合でも、これに遭遇します。私はtest_after_commitジェムを使用していますが、それでうまくいくようです。

于 2014-04-01T00:31:21.933 に答える
2

このGistは私を助けました。

トランザクション フィクスチャを使用している場合でも、ActiveRecord にモンキー パッチを適用して after_commit コールバックを起動します。

module ActiveRecord
  module ConnectionAdapters
    module DatabaseStatements
      #
      # Run the normal transaction method; when it's done, check to see if there
      # is exactly one open transaction. If so, that's the transactional
      # fixtures transaction; from the model's standpoint, the completed
      # transaction is the real deal. Send commit callbacks to models.
      #
      # If the transaction block raises a Rollback, we need to know, so we don't
      # call the commit hooks. Other exceptions don't need to be explicitly
      # accounted for since they will raise uncaught through this method and
      # prevent the code after the hook from running.
      #
      def transaction_with_transactional_fixtures(options = {}, &block)
        rolled_back = false

        transaction_without_transactional_fixtures do
          begin
            yield
          rescue ActiveRecord::Rollback => e
            rolled_back = true
            raise e
          end
        end

        if !rolled_back && open_transactions == 1
          commit_transaction_records(false)
        end
      end
      alias_method_chain :transaction, :transactional_fixtures

      #
      # The @_current_transaction_records is an stack of arrays, each one
      # containing the records associated with the corresponding transaction
      # in the transaction stack. This is used by the
      # `rollback_transaction_records` method (to only send a rollback hook to
      # models attached to the transaction being rolled back) but is usually
      # ignored by the `commit_transaction_records` method. Here we
      # monkey-patch it to temporarily replace the array with only the records
      # for the top-of-stack transaction, so the real
      # `commit_transaction_records` method only sends callbacks to those.
      #
      def commit_transaction_records_with_transactional_fixtures(commit = true)
        unless commit
          real_current_transaction_records = @_current_transaction_records
          @_current_transaction_records = @_current_transaction_records.pop
        end

        begin
          commit_transaction_records_without_transactional_fixtures
        rescue # works better with that :)
        ensure
          unless commit
            @_current_transaction_records = real_current_transaction_records
         end
        end
      end
      alias_method_chain :commit_transaction_records, :transactional_fixtures
    end
  end
end

この新しいファイルを Rails.root/spec/support ディレクトリに置きますspec/support/after_commit_with_transactional_fixtures.rb

Rails 3 はそれをテスト環境に自動的にロードします。

于 2012-07-18T18:22:12.993 に答える