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.
Files changed (57) hide show
  1. data/Gemfile.lock +150 -82
  2. data/History.txt +19 -1
  3. data/README.textile +61 -59
  4. data/Rakefile +7 -17
  5. data/VERSION.yml +3 -3
  6. data/examples/Gemfile +14 -20
  7. data/examples/Gemfile.lock +150 -82
  8. data/examples/features/step_definitions/translation_steps.rb +14 -14
  9. data/examples/features/support/env.rb +6 -2
  10. data/features/cleaning.feature +1 -1
  11. data/features/cleaning_default_strategy.feature +1 -1
  12. data/features/cleaning_multiple_dbs.feature +1 -2
  13. data/features/cleaning_multiple_orms.feature +7 -7
  14. data/features/support/env.rb +1 -1
  15. data/lib/database_cleaner/active_record/base.rb +26 -6
  16. data/lib/database_cleaner/active_record/deletion.rb +2 -2
  17. data/lib/database_cleaner/active_record/transaction.rb +9 -9
  18. data/lib/database_cleaner/active_record/truncation.rb +157 -50
  19. data/lib/database_cleaner/base.rb +2 -2
  20. data/lib/database_cleaner/configuration.rb +26 -3
  21. data/lib/database_cleaner/data_mapper/truncation.rb +2 -2
  22. data/lib/database_cleaner/generic/truncation.rb +7 -5
  23. data/lib/database_cleaner/mongo/base.rb +16 -0
  24. data/lib/database_cleaner/mongo/truncation.rb +9 -14
  25. data/lib/database_cleaner/mongo/truncation_mixin.rb +22 -0
  26. data/lib/database_cleaner/mongo_mapper/truncation.rb +2 -2
  27. data/lib/database_cleaner/mongoid/truncation.rb +2 -2
  28. data/lib/database_cleaner/moped/truncation.rb +6 -2
  29. data/lib/database_cleaner/sequel/truncation.rb +6 -6
  30. data/spec/database_cleaner/active_record/base_spec.rb +27 -15
  31. data/spec/database_cleaner/active_record/truncation/mysql2_spec.rb +40 -0
  32. data/spec/database_cleaner/active_record/truncation/mysql_spec.rb +40 -0
  33. data/spec/database_cleaner/active_record/truncation/postgresql_spec.rb +48 -0
  34. data/spec/database_cleaner/active_record/truncation/shared_fast_truncation.rb +40 -0
  35. data/spec/database_cleaner/active_record/truncation_spec.rb +102 -33
  36. data/spec/database_cleaner/base_spec.rb +14 -14
  37. data/spec/database_cleaner/configuration_spec.rb +15 -10
  38. data/spec/database_cleaner/data_mapper/base_spec.rb +1 -1
  39. data/spec/database_cleaner/data_mapper/transaction_spec.rb +1 -1
  40. data/spec/database_cleaner/data_mapper/truncation_spec.rb +1 -1
  41. data/spec/database_cleaner/generic/base_spec.rb +1 -1
  42. data/spec/database_cleaner/generic/truncation_spec.rb +35 -5
  43. data/spec/database_cleaner/mongo/mongo_examples.rb +26 -0
  44. data/spec/database_cleaner/mongo/truncation_spec.rb +72 -0
  45. data/spec/database_cleaner/mongo_mapper/base_spec.rb +1 -1
  46. data/spec/database_cleaner/sequel/base_spec.rb +1 -1
  47. data/spec/database_cleaner/sequel/transaction_spec.rb +1 -1
  48. data/spec/database_cleaner/sequel/truncation_spec.rb +1 -1
  49. data/spec/database_cleaner/{shared_strategy_spec.rb → shared_strategy.rb} +0 -0
  50. data/spec/spec_helper.rb +6 -4
  51. data/spec/support/active_record/database_setup.rb +4 -0
  52. data/spec/support/active_record/mysql2_setup.rb +38 -0
  53. data/spec/support/active_record/mysql_setup.rb +38 -0
  54. data/spec/support/active_record/postgresql_setup.rb +41 -0
  55. data/spec/support/active_record/schema_setup.rb +10 -0
  56. metadata +313 -46
  57. 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? :connection
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 && self.strategy.class == other.strategy.class
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
- @connections ||= []
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
- connections.push cleaner
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
- @connections ||= [::DatabaseCleaner::Base.new]
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)
@@ -166,8 +166,8 @@ module DatabaseCleaner
166
166
  end
167
167
 
168
168
  # overwritten
169
- def migration_storage_name
170
- 'migration_info'
169
+ def migration_storage_names
170
+ %w[migration_info]
171
171
  end
172
172
 
173
173
  end
@@ -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 and :except. You specified #{opts.keys.join(',')}."
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 << migration_storage_name if migration_storage_name
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 migration_storage_name
33
- nil
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
- module Truncation
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
-
6
+ class Truncation
7
+ include ::DatabaseCleaner::Generic::Truncation
8
+ include TruncationMixin
9
+ include Base
14
10
  private
15
11
 
16
- def collections
17
- database.collections.select { |c| c.name !~ /^system\./ }
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/truncation'
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::Truncation
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/truncation'
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::Truncation
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].drop if @only.include?(c.name) }
7
+ collections.each { |c| session[c].find.remove_all if @only.include?(c) }
8
8
  else
9
- collections.each { |c| session[c].drop unless @tables_to_exclude.include?(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 db_type= db.url.sub(/:.+/,'').to_sym
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 migration_storage_name
43
- :schema_info
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/shared_strategy_spec'
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 "create_connection_klass" do
114
+ describe "create_connection_class" do
109
115
  it "should return a class" do
110
- subject.create_connection_klass.should be_a(Class)
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.create_connection_klass.ancestors.should include(::ActiveRecord::Base)
120
+ subject.create_connection_class.ancestors.should include(::ActiveRecord::Base)
115
121
  end
116
122
  end
117
123
 
118
- describe "connection_klass" do
119
- it { expect{ subject.connection_klass }.to_not raise_error }
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.connection_klass.should == ::ActiveRecord::Base
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 connection_klass if it doesnt exist if connection_hash is set" do
129
- subject.should_receive(:create_connection_klass).and_return(mock('class').as_null_object)
130
- subject.connection_klass
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 create_connection_klass if connection_hash is set" do
134
- klass = mock('klass')
135
- klass.should_receive(:establish_connection).with(hash)
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(:create_connection_klass).and_return(klass)
138
- subject.connection_klass
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
+