From a96c0d5f931f825de80914ac28729a3b7b6c30a2 Mon Sep 17 00:00:00 2001 From: Ben Mabey Date: Wed, 4 Mar 2009 21:31:00 -0700 Subject: [PATCH] truncation AR strategy now takes :only and :except so you can manage the tables you want to truncate --- .../active_record/truncation.rb | 22 ++++++- .../active_record/truncation_spec.rb | 66 +++++++++++++++++++ spec/database_cleaner/configuration_spec.rb | 11 ++++ spec/spec.opts | 1 + spec/spec_helper.rb | 1 + 5 files changed, 98 insertions(+), 3 deletions(-) create mode 100644 spec/database_cleaner/active_record/truncation_spec.rb diff --git a/lib/database_cleaner/active_record/truncation.rb b/lib/database_cleaner/active_record/truncation.rb index dfe566f..9c01ff3 100644 --- a/lib/database_cleaner/active_record/truncation.rb +++ b/lib/database_cleaner/active_record/truncation.rb @@ -2,7 +2,7 @@ module ActiveRecord module ConnectionAdapters class MysqlAdapter - def truncate_tabe(table_name) + def truncate_table(table_name) execute("TRUNCATE TABLE #{table_name};") end end @@ -21,6 +21,18 @@ end module DatabaseCleaner::ActiveRecord class Truncation + def initialize(options={}) + if !options.empty? && !(options.keys - [:only, :except]).empty? + raise ArgumentError, "The only valid options are :only and :except. You specified #{options.keys.join(',')}." + end + if options.has_key?(:only) && options.has_key?(:except) + raise ArgumentError, "You may only specify either :only or :either. Doing both doesn't really make sense does it?" + end + + @only = options[:only] + @tables_to_exclude = (options[:except] || []) << 'schema_migrations' + end + def start # no-op end @@ -28,7 +40,7 @@ module DatabaseCleaner::ActiveRecord def clean connection.disable_referential_integrity do - (connection.tables - %w{schema_migrations}).each do |table_name| + tables_to_truncate.each do |table_name| connection.truncate_table table_name end end @@ -36,8 +48,12 @@ module DatabaseCleaner::ActiveRecord private + def tables_to_truncate + (@only || connection.tables) - @tables_to_exclude + end + def connection - ActiveRecord::Base.connection + ::ActiveRecord::Base.connection end end diff --git a/spec/database_cleaner/active_record/truncation_spec.rb b/spec/database_cleaner/active_record/truncation_spec.rb new file mode 100644 index 0000000..1ad7905 --- /dev/null +++ b/spec/database_cleaner/active_record/truncation_spec.rb @@ -0,0 +1,66 @@ +require File.dirname(__FILE__) + '/../../spec_helper' +require 'database_cleaner/active_record/truncation' +require 'active_record' +#module ActiveRecord + #module ConnectionAdapters + #[MysqlAdapter, SQLite3Adapter].each do |adapter| + #describe adapter, "#truncate_table" do + #it "should truncate the table" + #end + #end + #end +#end + +module DatabaseCleaner + module ActiveRecord + + describe Truncation do + before(:each) do + @connection = mock('connection') + @connection.stub!(:disable_referential_integrity).and_yield + ::ActiveRecord::Base.stub!(:connection).and_return(@connection) + end + + it "should truncate all tables except for schema_migrations" do + @connection.stub!(:tables).and_return(%w[schema_migrations widgets dogs]) + + @connection.should_receive(:truncate_table).with('widgets') + @connection.should_receive(:truncate_table).with('dogs') + @connection.should_not_receive(:truncate_table).with('schema_migrations') + + Truncation.new.clean + end + + it "should only truncate the tables specified in the :only option when provided" do + @connection.stub!(:tables).and_return(%w[schema_migrations widgets dogs]) + + @connection.should_receive(:truncate_table).with('widgets') + @connection.should_not_receive(:truncate_table).with('dogs') + + Truncation.new(:only => ['widgets']).clean + end + + it "should not truncate the tables specified in the :except option" do + @connection.stub!(:tables).and_return(%w[schema_migrations widgets dogs]) + + @connection.should_receive(:truncate_table).with('dogs') + @connection.should_not_receive(:truncate_table).with('widgets') + + Truncation.new(:except => ['widgets']).clean + end + + it "should raise an error when :only and :except options are used" do + running { + Truncation.new(:except => ['widgets'], :only => ['widgets']) + }.should raise_error(ArgumentError) + end + + it "should raise an error when invalid options are provided" do + running { Truncation.new(:foo => 'bar') }.should raise_error(ArgumentError) + end + + + end + + end +end diff --git a/spec/database_cleaner/configuration_spec.rb b/spec/database_cleaner/configuration_spec.rb index 5efb379..66ee3e4 100644 --- a/spec/database_cleaner/configuration_spec.rb +++ b/spec/database_cleaner/configuration_spec.rb @@ -3,6 +3,16 @@ require 'database_cleaner/active_record/transaction' require 'database_cleaner/data_mapper/transaction' describe DatabaseCleaner do + + # These examples muck around with the constants for autodetection so we need to clean up.... + before(:all) do + TempAR = ActiveRecord unless defined?(TempAR) + # need to add one for each ORM that we load in the spec helper... + end + after(:all) do + ActiveRecord = TempAR + end + before(:each) do DatabaseCleaner::ActiveRecord::Transaction.stub!(:new).and_return(@strategy = mock('strategy')) Object.const_set('ActiveRecord', "just mocking out the constant here...") unless defined?(::ActiveRecord) @@ -64,4 +74,5 @@ describe DatabaseCleaner do end end end + end diff --git a/spec/spec.opts b/spec/spec.opts index e211c6b..8c1da55 100644 --- a/spec/spec.opts +++ b/spec/spec.opts @@ -3,3 +3,4 @@ --loadby mtime --reverse +--backtrace diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 11bdbe8..bd44bc0 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,5 +1,6 @@ require 'rubygems' require 'spec' +require 'activerecord' $:.unshift(File.dirname(__FILE__) + '/../lib') require 'database_cleaner'