Create a gist now

Instantly share code, notes, and snippets.

# In Rspec, gives you:
# before(:all_transactional) {}
#
# Uses nested transactions to correctly rollback :all before blocks
# You *may* need to reload some instance variables in a separate before(:each) block
# All a bit of a hack, but really handy
module RspecRailsTransactions
def before_all_transactional_parts # :nodoc:
@before_all_transactional_parts ||= []
end
# Overridden from rspec implementation to add :all_transactional
def before_parts(scope)
case scope
when :each; before_each_parts
when :all; before_all_parts
when :suite; before_suite_parts
when :all_transactional; before_all_transactional_parts
end
end
# Based on a combination of run_before_all and run_after_all methods from rspec
def run_before_all_transactional_parts(success, run_options, instance_variables)
return [success, instance_variables] if example_group_hierarchy.before_all_transactional_parts.empty?
example_proxy = ::Spec::Example::ExampleProxy.new("before(:all_transactional)")
before_all = new(example_proxy)
before_all.set_instance_variables_from_hash(instance_variables)
example_group_hierarchy.run_before_all_transactional(before_all)
[success, before_all.instance_variable_hash]
rescue Exception => e
run_options.reporter.example_failed(example_proxy, e)
[false, before_all.instance_variable_hash]
end
# Overridden from the rspec implementation, as it doesn't provide us with necessary hooks
def run_examples(success, instance_variables, examples, run_options)
return [success, instance_variables] unless success
after_all_instance_variables = instance_variables
ActiveSupport::TestCase.use_transactional_fixtures = false
ActiveRecord::Base.transaction(:joinable => false) do
success, instance_variables = run_before_all_transactional_parts(success, run_options, instance_variables)
if success
examples.each do |example|
example_group_instance = new(example, &example_implementations[example])
# .transaction doesn't work here
ActiveRecord::Base.connection.create_savepoint
ActiveRecord::Base.connection.increment_open_transactions
success &= example_group_instance.execute(run_options, instance_variables)
ActiveRecord::Base.connection.decrement_open_transactions
ActiveRecord::Base.connection.rollback_to_savepoint
after_all_instance_variables = example_group_instance.instance_variable_hash
end
end
raise ActiveRecord::Rollback
end
return [success, after_all_instance_variables]
end
end
module Spec
module Example
class ExampleGroupHierarchy < Array
# Fail fast call was cargo-culted, I need to investigate further
def run_before_all_transactional(example)
example.eval_each_fail_fast(before_all_transactional_parts)
end
# Not all of the hierachy has necessary been extended with transactional
# support, so check that each klass responds to the method first
def before_all_transactional_parts
@before_all_transactional_parts ||= collect {|klass| klass.before_all_transactional_parts if klass.respond_to?(:before_all_transactional_parts) }.compact.flatten
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment