database_cleaner 0.8.0 → 0.9.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +150 -82
- data/History.txt +19 -1
- data/README.textile +61 -59
- data/Rakefile +7 -17
- data/VERSION.yml +3 -3
- data/examples/Gemfile +14 -20
- data/examples/Gemfile.lock +150 -82
- data/examples/features/step_definitions/translation_steps.rb +14 -14
- data/examples/features/support/env.rb +6 -2
- data/features/cleaning.feature +1 -1
- data/features/cleaning_default_strategy.feature +1 -1
- data/features/cleaning_multiple_dbs.feature +1 -2
- data/features/cleaning_multiple_orms.feature +7 -7
- data/features/support/env.rb +1 -1
- data/lib/database_cleaner/active_record/base.rb +26 -6
- data/lib/database_cleaner/active_record/deletion.rb +2 -2
- data/lib/database_cleaner/active_record/transaction.rb +9 -9
- data/lib/database_cleaner/active_record/truncation.rb +157 -50
- data/lib/database_cleaner/base.rb +2 -2
- data/lib/database_cleaner/configuration.rb +26 -3
- data/lib/database_cleaner/data_mapper/truncation.rb +2 -2
- data/lib/database_cleaner/generic/truncation.rb +7 -5
- data/lib/database_cleaner/mongo/base.rb +16 -0
- data/lib/database_cleaner/mongo/truncation.rb +9 -14
- data/lib/database_cleaner/mongo/truncation_mixin.rb +22 -0
- data/lib/database_cleaner/mongo_mapper/truncation.rb +2 -2
- data/lib/database_cleaner/mongoid/truncation.rb +2 -2
- data/lib/database_cleaner/moped/truncation.rb +6 -2
- data/lib/database_cleaner/sequel/truncation.rb +6 -6
- data/spec/database_cleaner/active_record/base_spec.rb +27 -15
- data/spec/database_cleaner/active_record/truncation/mysql2_spec.rb +40 -0
- data/spec/database_cleaner/active_record/truncation/mysql_spec.rb +40 -0
- data/spec/database_cleaner/active_record/truncation/postgresql_spec.rb +48 -0
- data/spec/database_cleaner/active_record/truncation/shared_fast_truncation.rb +40 -0
- data/spec/database_cleaner/active_record/truncation_spec.rb +102 -33
- data/spec/database_cleaner/base_spec.rb +14 -14
- data/spec/database_cleaner/configuration_spec.rb +15 -10
- data/spec/database_cleaner/data_mapper/base_spec.rb +1 -1
- data/spec/database_cleaner/data_mapper/transaction_spec.rb +1 -1
- data/spec/database_cleaner/data_mapper/truncation_spec.rb +1 -1
- data/spec/database_cleaner/generic/base_spec.rb +1 -1
- data/spec/database_cleaner/generic/truncation_spec.rb +35 -5
- data/spec/database_cleaner/mongo/mongo_examples.rb +26 -0
- data/spec/database_cleaner/mongo/truncation_spec.rb +72 -0
- data/spec/database_cleaner/mongo_mapper/base_spec.rb +1 -1
- data/spec/database_cleaner/sequel/base_spec.rb +1 -1
- data/spec/database_cleaner/sequel/transaction_spec.rb +1 -1
- data/spec/database_cleaner/sequel/truncation_spec.rb +1 -1
- data/spec/database_cleaner/{shared_strategy_spec.rb → shared_strategy.rb} +0 -0
- data/spec/spec_helper.rb +6 -4
- data/spec/support/active_record/database_setup.rb +4 -0
- data/spec/support/active_record/mysql2_setup.rb +38 -0
- data/spec/support/active_record/mysql_setup.rb +38 -0
- data/spec/support/active_record/postgresql_setup.rb +41 -0
- data/spec/support/active_record/schema_setup.rb +10 -0
- metadata +313 -46
- data/spec/spec.opts +0 -7
@@ -8,7 +8,7 @@ module DatabaseCleaner
|
|
8
8
|
else
|
9
9
|
self.orm = desired_orm
|
10
10
|
end
|
11
|
-
self.db = opts[:connection] if opts.has_key? :
|
11
|
+
self.db = opts[:connection] || opts[:model] if opts.has_key?(:connection) || opts.has_key?(:model)
|
12
12
|
set_default_orm_strategy
|
13
13
|
end
|
14
14
|
|
@@ -85,7 +85,7 @@ module DatabaseCleaner
|
|
85
85
|
|
86
86
|
#TODO make strategies directly comparable
|
87
87
|
def ==(other)
|
88
|
-
self.orm == other.orm && self.db == other.db
|
88
|
+
self.orm == other.orm && self.db == other.db
|
89
89
|
end
|
90
90
|
|
91
91
|
private
|
@@ -6,11 +6,29 @@ module DatabaseCleaner
|
|
6
6
|
class UnknownStrategySpecified < ArgumentError; end
|
7
7
|
|
8
8
|
class << self
|
9
|
+
def init_cleaners
|
10
|
+
@cleaners ||= {}
|
11
|
+
# ghetto ordered hash.. maintains 1.8 compat and old API
|
12
|
+
@connections ||= []
|
13
|
+
end
|
14
|
+
|
9
15
|
def [](orm,opts = {})
|
10
16
|
raise NoORMDetected unless orm
|
11
|
-
|
17
|
+
init_cleaners
|
18
|
+
# TODO: deprecate
|
19
|
+
# this method conflates creation with lookup. Both a command and a query. Yuck.
|
20
|
+
if @cleaners.has_key? [orm, opts]
|
21
|
+
@cleaners[[orm, opts]]
|
22
|
+
else
|
23
|
+
add_cleaner(orm, opts)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def add_cleaner(orm,opts = {})
|
28
|
+
init_cleaners
|
12
29
|
cleaner = DatabaseCleaner::Base.new(orm,opts)
|
13
|
-
|
30
|
+
@cleaners[[orm, opts]] = cleaner
|
31
|
+
@connections << cleaner
|
14
32
|
cleaner
|
15
33
|
end
|
16
34
|
|
@@ -23,7 +41,12 @@ module DatabaseCleaner
|
|
23
41
|
end
|
24
42
|
|
25
43
|
def connections
|
26
|
-
|
44
|
+
# double yuck.. can't wait to deprecate this whole class...
|
45
|
+
unless @cleaners
|
46
|
+
autodetected = ::DatabaseCleaner::Base.new
|
47
|
+
add_cleaner(autodetected.orm)
|
48
|
+
end
|
49
|
+
@connections
|
27
50
|
end
|
28
51
|
|
29
52
|
def logger=(log_source)
|
@@ -2,8 +2,8 @@ module DatabaseCleaner
|
|
2
2
|
module Generic
|
3
3
|
module Truncation
|
4
4
|
def initialize(opts={})
|
5
|
-
if !opts.empty? && !(opts.keys - [:only, :except]).empty?
|
6
|
-
raise ArgumentError, "The only valid options are :only
|
5
|
+
if !opts.empty? && !(opts.keys - [:only, :except, :pre_count, :reset_ids]).empty?
|
6
|
+
raise ArgumentError, "The only valid options are :only, :except, :pre_count or :reset_ids. You specified #{opts.keys.join(',')}."
|
7
7
|
end
|
8
8
|
if opts.has_key?(:only) && opts.has_key?(:except)
|
9
9
|
raise ArgumentError, "You may only specify either :only or :except. Doing both doesn't really make sense does it?"
|
@@ -11,7 +11,9 @@ module DatabaseCleaner
|
|
11
11
|
|
12
12
|
@only = opts[:only]
|
13
13
|
@tables_to_exclude = (opts[:except] || []).dup
|
14
|
-
@tables_to_exclude
|
14
|
+
@tables_to_exclude += migration_storage_names
|
15
|
+
@pre_count = opts[:pre_count]
|
16
|
+
@reset_ids = opts[:reset_ids]
|
15
17
|
end
|
16
18
|
|
17
19
|
def start
|
@@ -29,8 +31,8 @@ module DatabaseCleaner
|
|
29
31
|
|
30
32
|
# overwrite in subclasses
|
31
33
|
# default implementation given because migration storage need not be present
|
32
|
-
def
|
33
|
-
|
34
|
+
def migration_storage_names
|
35
|
+
%w[]
|
34
36
|
end
|
35
37
|
end
|
36
38
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module DatabaseCleaner
|
2
|
+
module Mongo
|
3
|
+
def self.available_strategies
|
4
|
+
%w[truncation]
|
5
|
+
end
|
6
|
+
module Base
|
7
|
+
def db=(desired_db)
|
8
|
+
@db = desired_db
|
9
|
+
end
|
10
|
+
|
11
|
+
def db
|
12
|
+
@db || raise("You have not specified a database. (see Mongo::Database)")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -1,22 +1,17 @@
|
|
1
|
+
require 'database_cleaner/mongo/base'
|
2
|
+
require 'database_cleaner/generic/truncation'
|
3
|
+
require 'database_cleaner/mongo/truncation_mixin'
|
1
4
|
module DatabaseCleaner
|
2
5
|
module Mongo
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
collections.each { |c| c.remove if @only.include?(c.name) }
|
8
|
-
else
|
9
|
-
collections.each { |c| c.remove unless @tables_to_exclude.include?(c.name) }
|
10
|
-
end
|
11
|
-
true
|
12
|
-
end
|
13
|
-
|
6
|
+
class Truncation
|
7
|
+
include ::DatabaseCleaner::Generic::Truncation
|
8
|
+
include TruncationMixin
|
9
|
+
include Base
|
14
10
|
private
|
15
11
|
|
16
|
-
def
|
17
|
-
|
12
|
+
def database
|
13
|
+
db
|
18
14
|
end
|
19
|
-
|
20
15
|
end
|
21
16
|
end
|
22
17
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module DatabaseCleaner
|
2
|
+
module Mongo
|
3
|
+
module TruncationMixin
|
4
|
+
|
5
|
+
def clean
|
6
|
+
if @only
|
7
|
+
collections.each { |c| c.remove if @only.include?(c.name) }
|
8
|
+
else
|
9
|
+
collections.each { |c| c.remove unless @tables_to_exclude.include?(c.name) }
|
10
|
+
end
|
11
|
+
true
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def collections
|
17
|
+
database.collections.select { |c| c.name !~ /^system\./ }
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -1,13 +1,13 @@
|
|
1
1
|
require 'database_cleaner/mongo_mapper/base'
|
2
2
|
require 'database_cleaner/generic/truncation'
|
3
|
-
require 'database_cleaner/mongo/
|
3
|
+
require 'database_cleaner/mongo/truncation_mixin'
|
4
4
|
|
5
5
|
module DatabaseCleaner
|
6
6
|
module MongoMapper
|
7
7
|
class Truncation
|
8
8
|
include ::DatabaseCleaner::MongoMapper::Base
|
9
9
|
include ::DatabaseCleaner::Generic::Truncation
|
10
|
-
include ::DatabaseCleaner::Mongo::
|
10
|
+
include ::DatabaseCleaner::Mongo::TruncationMixin
|
11
11
|
|
12
12
|
private
|
13
13
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'database_cleaner/mongoid/base'
|
2
2
|
require 'database_cleaner/generic/truncation'
|
3
|
-
require 'database_cleaner/mongo/
|
3
|
+
require 'database_cleaner/mongo/truncation_mixin'
|
4
4
|
require 'database_cleaner/moped/truncation'
|
5
5
|
require 'mongoid/version'
|
6
6
|
|
@@ -12,7 +12,7 @@ module DatabaseCleaner
|
|
12
12
|
|
13
13
|
if ::Mongoid::VERSION < '3'
|
14
14
|
|
15
|
-
include ::DatabaseCleaner::Mongo::
|
15
|
+
include ::DatabaseCleaner::Mongo::TruncationMixin
|
16
16
|
|
17
17
|
private
|
18
18
|
|
@@ -4,9 +4,9 @@ module DatabaseCleaner
|
|
4
4
|
|
5
5
|
def clean
|
6
6
|
if @only
|
7
|
-
collections.each { |c| session[c].
|
7
|
+
collections.each { |c| session[c].find.remove_all if @only.include?(c) }
|
8
8
|
else
|
9
|
-
collections.each { |c| session[c].
|
9
|
+
collections.each { |c| session[c].find.remove_all unless @tables_to_exclude.include?(c) }
|
10
10
|
end
|
11
11
|
true
|
12
12
|
end
|
@@ -14,6 +14,10 @@ module DatabaseCleaner
|
|
14
14
|
private
|
15
15
|
|
16
16
|
def collections
|
17
|
+
if db != :default
|
18
|
+
session.use(db)
|
19
|
+
end
|
20
|
+
|
17
21
|
session['system.namespaces'].find(:name => { '$not' => /system|\$/ }).to_a.map do |collection|
|
18
22
|
_, name = collection['name'].split('.', 2)
|
19
23
|
name
|
@@ -6,9 +6,9 @@ module DatabaseCleaner
|
|
6
6
|
class Truncation
|
7
7
|
include ::DatabaseCleaner::Sequel::Base
|
8
8
|
include ::DatabaseCleaner::Generic::Truncation
|
9
|
-
|
9
|
+
|
10
10
|
def clean
|
11
|
-
case
|
11
|
+
case db.database_type
|
12
12
|
when :postgres
|
13
13
|
# PostgreSQL requires all tables with FKs to be truncates in the same command, or have the CASCADE keyword
|
14
14
|
# appended. Bulk truncation without CASCADE is:
|
@@ -25,7 +25,7 @@ module DatabaseCleaner
|
|
25
25
|
end
|
26
26
|
end
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
29
|
def each_table
|
30
30
|
tables_to_truncate(db).each do |table|
|
31
31
|
yield db, table
|
@@ -33,14 +33,14 @@ module DatabaseCleaner
|
|
33
33
|
end
|
34
34
|
|
35
35
|
private
|
36
|
-
|
36
|
+
|
37
37
|
def tables_to_truncate(db)
|
38
38
|
(@only || db.tables) - @tables_to_exclude
|
39
39
|
end
|
40
40
|
|
41
41
|
# overwritten
|
42
|
-
def
|
43
|
-
|
42
|
+
def migration_storage_names
|
43
|
+
%w[schema_info schema_migrations]
|
44
44
|
end
|
45
45
|
|
46
46
|
end
|
@@ -1,7 +1,13 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'active_record'
|
3
3
|
require 'database_cleaner/active_record/base'
|
4
|
-
require 'database_cleaner/
|
4
|
+
require 'database_cleaner/shared_strategy'
|
5
|
+
|
6
|
+
class FakeModel
|
7
|
+
def self.connection
|
8
|
+
:fake_connection
|
9
|
+
end
|
10
|
+
end
|
5
11
|
|
6
12
|
module DatabaseCleaner
|
7
13
|
describe ActiveRecord do
|
@@ -105,37 +111,43 @@ my_db:
|
|
105
111
|
end
|
106
112
|
end
|
107
113
|
|
108
|
-
describe "
|
114
|
+
describe "create_connection_class" do
|
109
115
|
it "should return a class" do
|
110
|
-
subject.
|
116
|
+
subject.create_connection_class.should be_a(Class)
|
111
117
|
end
|
112
118
|
|
113
119
|
it "should return a class extending ::ActiveRecord::Base" do
|
114
|
-
subject.
|
120
|
+
subject.create_connection_class.ancestors.should include(::ActiveRecord::Base)
|
115
121
|
end
|
116
122
|
end
|
117
123
|
|
118
|
-
describe "
|
119
|
-
it { expect{ subject.
|
124
|
+
describe "connection_class" do
|
125
|
+
it { expect{ subject.connection_class }.to_not raise_error }
|
120
126
|
it "should default to ActiveRecord::Base" do
|
121
|
-
subject.
|
127
|
+
subject.connection_class.should == ::ActiveRecord::Base
|
128
|
+
end
|
129
|
+
|
130
|
+
it "allows for database models to be passed in" do
|
131
|
+
subject.db = FakeModel
|
132
|
+
subject.connection_class.should == FakeModel
|
122
133
|
end
|
123
134
|
|
124
135
|
context "when connection_hash is set" do
|
125
136
|
let(:hash) { mock("hash") }
|
137
|
+
before { ::ActiveRecord::Base.stub!(:respond_to?).and_return(false)}
|
126
138
|
before { subject.stub(:connection_hash).and_return(hash) }
|
127
139
|
|
128
|
-
it "should create
|
129
|
-
subject.should_receive(:
|
130
|
-
subject.
|
140
|
+
it "should create connection_class if it doesnt exist if connection_hash is set" do
|
141
|
+
subject.should_receive(:create_connection_class).and_return(mock('class').as_null_object)
|
142
|
+
subject.connection_class
|
131
143
|
end
|
132
144
|
|
133
|
-
it "should configure the class from
|
134
|
-
|
135
|
-
|
145
|
+
it "should configure the class from create_connection_class if connection_hash is set" do
|
146
|
+
strategy_class = mock('strategy_class')
|
147
|
+
strategy_class.should_receive(:establish_connection).with(hash)
|
136
148
|
|
137
|
-
subject.should_receive(:
|
138
|
-
subject.
|
149
|
+
subject.should_receive(:create_connection_class).and_return(strategy_class)
|
150
|
+
subject.connection_class
|
139
151
|
end
|
140
152
|
end
|
141
153
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'active_record'
|
3
|
+
require 'support/active_record/mysql2_setup'
|
4
|
+
require 'database_cleaner/active_record/truncation'
|
5
|
+
require 'database_cleaner/active_record/truncation/shared_fast_truncation'
|
6
|
+
|
7
|
+
module ActiveRecord
|
8
|
+
module ConnectionAdapters
|
9
|
+
describe do
|
10
|
+
before(:all) { active_record_mysql2_setup }
|
11
|
+
|
12
|
+
let(:adapter) { Mysql2Adapter }
|
13
|
+
let(:connection) { active_record_mysql2_connection }
|
14
|
+
|
15
|
+
describe "#truncate_table" do
|
16
|
+
it "should truncate the table" do
|
17
|
+
2.times { User.create }
|
18
|
+
|
19
|
+
connection.truncate_table('users')
|
20
|
+
User.count.should == 0
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should reset AUTO_INCREMENT index of table" do
|
24
|
+
2.times { User.create }
|
25
|
+
User.delete_all
|
26
|
+
|
27
|
+
connection.truncate_table('users')
|
28
|
+
|
29
|
+
User.create.id.should == 1
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
it_behaves_like "an adapter with pre-count truncation" do
|
34
|
+
let(:adapter) { Mysql2Adapter }
|
35
|
+
let(:connection) { active_record_mysql2_connection }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'active_record'
|
3
|
+
require 'support/active_record/mysql_setup'
|
4
|
+
require 'database_cleaner/active_record/truncation'
|
5
|
+
require 'database_cleaner/active_record/truncation/shared_fast_truncation'
|
6
|
+
|
7
|
+
module ActiveRecord
|
8
|
+
module ConnectionAdapters
|
9
|
+
describe do
|
10
|
+
before(:all) { active_record_mysql_setup }
|
11
|
+
|
12
|
+
let(:adapter) { MysqlAdapter }
|
13
|
+
let(:connection) { active_record_mysql_connection }
|
14
|
+
|
15
|
+
describe "#truncate_table" do
|
16
|
+
it "should truncate the table" do
|
17
|
+
2.times { User.create }
|
18
|
+
|
19
|
+
connection.truncate_table('users')
|
20
|
+
User.count.should == 0
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should reset AUTO_INCREMENT index of table" do
|
24
|
+
2.times { User.create }
|
25
|
+
User.delete_all
|
26
|
+
|
27
|
+
connection.truncate_table('users')
|
28
|
+
|
29
|
+
User.create.id.should == 1
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
it_behaves_like "an adapter with pre-count truncation" do
|
34
|
+
let(:adapter) { MysqlAdapter }
|
35
|
+
let(:connection) { active_record_mysql_connection }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'active_record'
|
3
|
+
require 'support/active_record/postgresql_setup'
|
4
|
+
require 'database_cleaner/active_record/truncation'
|
5
|
+
require 'database_cleaner/active_record/truncation/shared_fast_truncation'
|
6
|
+
|
7
|
+
module ActiveRecord
|
8
|
+
module ConnectionAdapters
|
9
|
+
describe do
|
10
|
+
before(:all) { active_record_pg_setup }
|
11
|
+
|
12
|
+
let(:adapter) { PostgreSQLAdapter }
|
13
|
+
|
14
|
+
let(:connection) do
|
15
|
+
active_record_pg_connection
|
16
|
+
end
|
17
|
+
|
18
|
+
before(:each) do
|
19
|
+
connection.truncate_tables connection.tables
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "#truncate_table" do
|
23
|
+
it "truncates the table" do
|
24
|
+
2.times { User.create }
|
25
|
+
|
26
|
+
connection.truncate_table('users')
|
27
|
+
User.count.should == 0
|
28
|
+
end
|
29
|
+
|
30
|
+
it "resets AUTO_INCREMENT index of table" do
|
31
|
+
2.times { User.create }
|
32
|
+
User.delete_all
|
33
|
+
|
34
|
+
connection.truncate_table('users')
|
35
|
+
|
36
|
+
User.create.id.should == 1
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
it_behaves_like "an adapter with pre-count truncation" do
|
41
|
+
let(:adapter) { PostgreSQLAdapter }
|
42
|
+
let(:connection) { active_record_pg_connection }
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|