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.
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
+