database_cleaner 0.8.0 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
|