Say you normally use the great database_cleaner
gem. Per the README
the standard setup is:
RSpec.configure do |config|
config.before(:suite) do
DatabaseCleaner.strategy = :transaction
DatabaseCleaner.clean_with(:truncation)
end
config.around(:each) do |example|
DatabaseCleaner.cleaning do
example.run
end
end
end
However, you have a subset of specs which you wish to not have the cleaner handle. By checking the metadata
in the around
hook, you can conditionally run the cleaner.
RSpec.configure do |config|
# Other setup
# RSpec 2 Metadata Config (Not necessary with RSpec 3)
# Ref https://www.relishapp.com/rspec/rspec-core/v/2-14/docs/metadata/user-defined-metadata
config.treat_symbols_as_metadata_keys_with_true_values = true
config.around do |example|
# BROKEN!
unless example.metadata[:no_database_cleaner]
DatabaseCleaner.cleaning(&example)
end
end
end
# Your spec file
require "spec_helper"
describe "Mystery database state", :no_database_cleaner do
it "does not use the cleaning process" do
end
end
Say your setup is a bit more complicated. Additionally, you've extracted the logic into a re-useable module which you share across different projects. By setting default metadata, and leveraging hook filters you can accomplish the same goal:
module DefaultDatabaseCleaning
# Your complex stuff
def self.included(klass)
# Other possible setup
klass.class_exec do
# Both `nil` and `false` are falsey, so we explicitly check for only
# `nil`; otherwise a user specificaly set `false`
metadata[:clean_database] = true if metadata[:clean_database].nil?
# Here we need to explicitly pass :each so we can set the filter
around :each, :clean_database do |example|
DatabaseCleaner.cleaning(&example)
end
end
end
end
# spec/spec_helper.rb
RSpec.configure do |config|
config.include DefaultDatabaseCleaning
end
# Your Spec file
require "spec_helper"
describe "Leveraging default metadata" do
it "default setting it to use cleaning" do
end
it "no cleaning here please", clean_database: false do
end
end
By combining the techniques and leveraging the fact that symbols are truthy. The metadata could pull double duty:
module DefaultDatabaseCleaning
def self.included(klass)
klass.class_exec do
metadata[:clean_database] = :transaction if metadata[:clean_database].nil?
around do |example|
# BROKEN!
if example.metadata[:clean_database]
DatabaseCleaner.strategy = example.metadata[:clean_database]
DatabaseCleaner.cleaning(&example)
end
end
end
end
end
# Your Spec file
require "spec_helper"
describe "Pulling double duty" do
context "Myster database state", clean_database: false do
it "does not use the cleaning process" {}
end
context "Using Redis here instead", clean_database: :truncation do
it "uses the truncation strategy" {}
end
end