surgical_strike 0.7.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. data/Gemfile.lock +163 -0
  2. data/History.txt +210 -0
  3. data/LICENSE +20 -0
  4. data/README.textile +229 -0
  5. data/TODO +3 -0
  6. data/VERSION.yml +5 -0
  7. data/cucumber.yml +1 -0
  8. data/examples/Gemfile +1 -0
  9. data/examples/Gemfile.lock +1 -0
  10. data/examples/config/database.yml.example +8 -0
  11. data/examples/db/sqlite_databases_go_here +0 -0
  12. data/examples/features/example.feature +11 -0
  13. data/examples/features/example_multiple_db.feature +23 -0
  14. data/examples/features/example_multiple_orm.feature +22 -0
  15. data/examples/features/step_definitions/activerecord_steps.rb +31 -0
  16. data/examples/features/step_definitions/couchpotato_steps.rb +31 -0
  17. data/examples/features/step_definitions/datamapper_steps.rb +37 -0
  18. data/examples/features/step_definitions/mongoid_steps.rb +23 -0
  19. data/examples/features/step_definitions/mongomapper_steps.rb +31 -0
  20. data/examples/features/step_definitions/translation_steps.rb +55 -0
  21. data/examples/features/support/env.rb +62 -0
  22. data/examples/lib/activerecord_models.rb +41 -0
  23. data/examples/lib/couchpotato_models.rb +61 -0
  24. data/examples/lib/datamapper_models.rb +50 -0
  25. data/examples/lib/mongoid_models.rb +49 -0
  26. data/examples/lib/mongomapper_models.rb +51 -0
  27. data/features/cleaning.feature +22 -0
  28. data/features/cleaning_default_strategy.feature +19 -0
  29. data/features/cleaning_multiple_dbs.feature +21 -0
  30. data/features/cleaning_multiple_orms.feature +29 -0
  31. data/features/step_definitions/database_cleaner_steps.rb +32 -0
  32. data/features/support/env.rb +7 -0
  33. data/features/support/feature_runner.rb +39 -0
  34. data/lib/database_cleaner/active_record/base.rb +53 -0
  35. data/lib/database_cleaner/active_record/deletion.rb +67 -0
  36. data/lib/database_cleaner/active_record/surgicalstrike.rb +65 -0
  37. data/lib/database_cleaner/active_record/transaction.rb +28 -0
  38. data/lib/database_cleaner/active_record/truncation.rb +152 -0
  39. data/lib/database_cleaner/base.rb +138 -0
  40. data/lib/database_cleaner/configuration.rb +94 -0
  41. data/lib/database_cleaner/couch_potato/base.rb +7 -0
  42. data/lib/database_cleaner/couch_potato/truncation.rb +28 -0
  43. data/lib/database_cleaner/cucumber.rb +11 -0
  44. data/lib/database_cleaner/data_mapper/base.rb +21 -0
  45. data/lib/database_cleaner/data_mapper/transaction.rb +26 -0
  46. data/lib/database_cleaner/data_mapper/truncation.rb +175 -0
  47. data/lib/database_cleaner/generic/base.rb +12 -0
  48. data/lib/database_cleaner/generic/surgicalstrike.rb +47 -0
  49. data/lib/database_cleaner/generic/truncation.rb +37 -0
  50. data/lib/database_cleaner/mongo/truncation.rb +22 -0
  51. data/lib/database_cleaner/mongo_mapper/base.rb +20 -0
  52. data/lib/database_cleaner/mongo_mapper/truncation.rb +19 -0
  53. data/lib/database_cleaner/mongoid/base.rb +20 -0
  54. data/lib/database_cleaner/mongoid/truncation.rb +20 -0
  55. data/lib/database_cleaner/null_strategy.rb +15 -0
  56. data/lib/database_cleaner/sequel/base.rb +22 -0
  57. data/lib/database_cleaner/sequel/transaction.rb +25 -0
  58. data/lib/database_cleaner/sequel/truncation.rb +50 -0
  59. data/lib/surgical_strike.rb +3 -0
  60. data/spec/database_cleaner/active_record/base_spec.rb +144 -0
  61. data/spec/database_cleaner/active_record/transaction_spec.rb +77 -0
  62. data/spec/database_cleaner/active_record/truncation_spec.rb +76 -0
  63. data/spec/database_cleaner/base_spec.rb +493 -0
  64. data/spec/database_cleaner/configuration_spec.rb +294 -0
  65. data/spec/database_cleaner/couch_potato/truncation_spec.rb +41 -0
  66. data/spec/database_cleaner/data_mapper/base_spec.rb +30 -0
  67. data/spec/database_cleaner/data_mapper/transaction_spec.rb +23 -0
  68. data/spec/database_cleaner/data_mapper/truncation_spec.rb +11 -0
  69. data/spec/database_cleaner/generic/base_spec.rb +22 -0
  70. data/spec/database_cleaner/generic/truncation_spec.rb +78 -0
  71. data/spec/database_cleaner/mongo_mapper/base_spec.rb +33 -0
  72. data/spec/database_cleaner/mongo_mapper/mongo_examples.rb +8 -0
  73. data/spec/database_cleaner/mongo_mapper/truncation_spec.rb +74 -0
  74. data/spec/database_cleaner/sequel/base_spec.rb +32 -0
  75. data/spec/database_cleaner/sequel/transaction_spec.rb +21 -0
  76. data/spec/database_cleaner/sequel/truncation_spec.rb +13 -0
  77. data/spec/database_cleaner/shared_strategy_spec.rb +13 -0
  78. data/spec/rcov.opts +1 -0
  79. data/spec/spec.opts +7 -0
  80. data/spec/spec_helper.rb +19 -0
  81. metadata +162 -0
@@ -0,0 +1,7 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../lib')
2
+ require 'database_cleaner'
3
+
4
+ require 'spec/expectations'
5
+
6
+ require 'test/unit/assertions'
7
+
@@ -0,0 +1,39 @@
1
+ class FeatureRunner
2
+ attr_accessor :orm
3
+ attr_accessor :another_orm
4
+ attr_accessor :multiple_databases
5
+ attr_accessor :strategy
6
+ attr_accessor :exit_status
7
+ attr_accessor :output
8
+
9
+ def strategy
10
+ @strategy || 'truncation'
11
+ end
12
+
13
+ def go(feature)
14
+ full_dir ||= File.expand_path(File.dirname(__FILE__) + "/../../examples/")
15
+ Dir.chdir(full_dir) do
16
+
17
+
18
+ ENV['ORM'] = orm
19
+ ENV['STRATEGY'] = strategy
20
+
21
+ if another_orm
22
+ ENV['ANOTHER_ORM'] = another_orm
23
+ else
24
+ ENV['ANOTHER_ORM'] = nil
25
+ end
26
+
27
+ if multiple_databases
28
+ ENV['MULTIPLE_DBS'] = "true"
29
+ else
30
+ ENV['MULTIPLE_DBS'] = nil
31
+ end
32
+
33
+ self.output = `#{"jruby -S " if defined?(JRUBY_VERSION)}cucumber features/#{feature}.feature`
34
+
35
+ self.exit_status = $?.exitstatus
36
+ end
37
+ end
38
+
39
+ end
@@ -0,0 +1,53 @@
1
+ require 'database_cleaner/generic/base'
2
+ require 'active_record'
3
+ require 'erb'
4
+
5
+ module DatabaseCleaner
6
+ module ActiveRecord
7
+
8
+ def self.available_strategies
9
+ %w[truncation transaction deletion]
10
+ end
11
+
12
+ def self.config_file_location=(path)
13
+ @config_file_location = path
14
+ end
15
+
16
+ def self.config_file_location
17
+ @config_file_location ||= "#{DatabaseCleaner.app_root}/config/database.yml"
18
+ end
19
+
20
+ module Base
21
+ include ::DatabaseCleaner::Generic::Base
22
+
23
+ attr_accessor :connection_hash
24
+
25
+ def db=(desired_db)
26
+ @db = desired_db
27
+ load_config
28
+ end
29
+
30
+ def db
31
+ @db || super
32
+ end
33
+
34
+ def load_config
35
+ if self.db != :default && File.file?(ActiveRecord.config_file_location)
36
+ connection_details = YAML::load(ERB.new(IO.read(ActiveRecord.config_file_location)).result)
37
+ @connection_hash = connection_details[self.db.to_s]
38
+ end
39
+ end
40
+
41
+ def create_connection_klass
42
+ Class.new(::ActiveRecord::Base)
43
+ end
44
+
45
+ def connection_klass
46
+ return ::ActiveRecord::Base unless connection_hash
47
+ klass = create_connection_klass
48
+ klass.send :establish_connection, connection_hash
49
+ klass
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,67 @@
1
+ require 'active_record/base'
2
+ require 'active_record/connection_adapters/abstract_adapter'
3
+ require "database_cleaner/generic/truncation"
4
+ require 'database_cleaner/active_record/base'
5
+ require 'database_cleaner/active_record/truncation'
6
+ # This file may seem to have duplication with that of truncation, but by keeping them separate
7
+ # we avoiding loading this code when it is not being used (which is the common case).
8
+
9
+ module ActiveRecord
10
+ module ConnectionAdapters
11
+
12
+ class MysqlAdapter < MYSQL_ADAPTER_PARENT
13
+ def delete_table(table_name)
14
+ execute("DELETE FROM #{quote_table_name(table_name)};")
15
+ end
16
+ end
17
+
18
+ class Mysql2Adapter < MYSQL2_ADAPTER_PARENT
19
+ def delete_table(table_name)
20
+ execute("DELETE FROM #{quote_table_name(table_name)};")
21
+ end
22
+ end
23
+
24
+ class JdbcAdapter < AbstractAdapter
25
+ def delete_table(table_name)
26
+ execute("DELETE FROM #{quote_table_name(table_name)};")
27
+ end
28
+ end
29
+
30
+ class PostgreSQLAdapter < AbstractAdapter
31
+ def delete_table(table_name)
32
+ execute("DELETE FROM #{quote_table_name(table_name)};")
33
+ end
34
+ end
35
+
36
+ class SQLServerAdapter < AbstractAdapter
37
+ def delete_table(table_name)
38
+ execute("DELETE FROM #{quote_table_name(table_name)};")
39
+ end
40
+ end
41
+
42
+ class OracleEnhancedAdapter < AbstractAdapter
43
+ def delete_table(table_name)
44
+ execute("DELETE FROM #{quote_table_name(table_name)}")
45
+ end
46
+ end
47
+
48
+ end
49
+ end
50
+
51
+
52
+ module DatabaseCleaner::ActiveRecord
53
+ class Deletion < Truncation
54
+
55
+ def clean
56
+ connection = connection_klass.connection
57
+ connection.disable_referential_integrity do
58
+ tables_to_truncate(connection).each do |table_name|
59
+ connection.delete_table table_name
60
+ end
61
+ end
62
+ end
63
+
64
+ end
65
+ end
66
+
67
+
@@ -0,0 +1,65 @@
1
+ require 'active_record/base'
2
+ require 'active_record/connection_adapters/abstract_adapter'
3
+ require 'database_cleaner/active_record/base'
4
+ require 'database_cleaner/generic/base'
5
+ require 'SurgicalStrike/generic/surgicalstrike'
6
+
7
+ module ActiveRecord
8
+ class Base
9
+ include ::DatabaseCleaner::Generic::Dataholder
10
+ extend ActiveRecord::Callbacks
11
+
12
+ after_create :add_vip
13
+
14
+ private
15
+ def add_vip
16
+ checktarget(self)
17
+ end
18
+ end
19
+
20
+ module ConnectionAdapters
21
+
22
+ class AbstractAdapter
23
+ def views
24
+ @views ||= select_values("select table_name from information_schema.views where table_schema = '#{current_database}'") rescue []
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ module DatabaseCleaner::ActiveRecord
31
+ class Surgicalstrike
32
+ include ::DatabaseCleaner::ActiveRecord::Base
33
+ include ::DatabaseCleaner::Generic::Dataholder
34
+ include ::DatabaseCleaner::Generic::Surgicalstrike
35
+
36
+ def start
37
+ connection = connection_klass.connection
38
+
39
+ $strike_targets = tables_to_strike(connection)
40
+ $vips = Array.new
41
+ end
42
+
43
+ def clean
44
+ strike_tables
45
+ end
46
+
47
+
48
+ private
49
+ def strike_tables
50
+ $vips = $vips.reverse
51
+ $vips.each do |record|
52
+ record.delete
53
+ end
54
+ end
55
+
56
+ def tables_to_strike(connection)
57
+ (@only || connection.tables) - @tables_to_exclude - connection.views
58
+ end
59
+
60
+ # overwritten
61
+ def migration_storage_name
62
+ 'schema_migrations'
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,28 @@
1
+ require 'database_cleaner/active_record/base'
2
+ module DatabaseCleaner::ActiveRecord
3
+ class Transaction
4
+ include ::DatabaseCleaner::ActiveRecord::Base
5
+
6
+ def start
7
+ if connection_klass.connection.respond_to?(:increment_open_transactions)
8
+ connection_klass.connection.increment_open_transactions
9
+ else
10
+ connection_klass.__send__(:increment_open_transactions)
11
+ end
12
+ connection_klass.connection.begin_db_transaction
13
+ end
14
+
15
+
16
+ def clean
17
+ return unless connection_klass.connection.open_transactions > 0
18
+
19
+ connection_klass.connection.rollback_db_transaction
20
+
21
+ if connection_klass.connection.respond_to?(:decrement_open_transactions)
22
+ connection_klass.connection.decrement_open_transactions
23
+ else
24
+ connection_klass.__send__(:decrement_open_transactions)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,152 @@
1
+ require 'active_record/base'
2
+ require 'active_record/connection_adapters/abstract_adapter'
3
+ require "database_cleaner/generic/truncation"
4
+ require 'database_cleaner/active_record/base'
5
+
6
+ module ActiveRecord
7
+ module ConnectionAdapters
8
+ # Activerecord-jdbc-adapter defines class dependencies a bit differently - if it is present, confirm to ArJdbc hierarchy to avoid 'superclass mismatch' errors.
9
+ USE_ARJDBC_WORKAROUND = defined?(ArJdbc)
10
+
11
+ class AbstractAdapter
12
+ def views
13
+ @views ||= select_values("select table_name from information_schema.views where table_schema = '#{current_database}'") rescue []
14
+ end
15
+
16
+ def truncate_table(table_name)
17
+ raise NotImplementedError
18
+ end
19
+
20
+ def truncate_tables(tables)
21
+ tables.each do |table_name|
22
+ self.truncate_table(table_name)
23
+ end
24
+ end
25
+ end
26
+
27
+ unless USE_ARJDBC_WORKAROUND
28
+ class SQLiteAdapter < AbstractAdapter
29
+ end
30
+ end
31
+
32
+ # ActiveRecord 3.1 support
33
+ if defined?(AbstractMysqlAdapter)
34
+ MYSQL_ADAPTER_PARENT = USE_ARJDBC_WORKAROUND ? JdbcAdapter : AbstractMysqlAdapter
35
+ MYSQL2_ADAPTER_PARENT = AbstractMysqlAdapter
36
+ else
37
+ MYSQL_ADAPTER_PARENT = USE_ARJDBC_WORKAROUND ? JdbcAdapter : AbstractAdapter
38
+ MYSQL2_ADAPTER_PARENT = AbstractAdapter
39
+ end
40
+
41
+ SQLITE_ADAPTER_PARENT = USE_ARJDBC_WORKAROUND ? JdbcAdapter : SQLiteAdapter
42
+ POSTGRE_ADAPTER_PARENT = USE_ARJDBC_WORKAROUND ? JdbcAdapter : AbstractAdapter
43
+
44
+ class MysqlAdapter < MYSQL_ADAPTER_PARENT
45
+ def truncate_table(table_name)
46
+ execute("TRUNCATE TABLE #{quote_table_name(table_name)};")
47
+ end
48
+ end
49
+
50
+ class Mysql2Adapter < MYSQL2_ADAPTER_PARENT
51
+ def truncate_table(table_name)
52
+ execute("TRUNCATE TABLE #{quote_table_name(table_name)};")
53
+ end
54
+ end
55
+
56
+ class IBM_DBAdapter < AbstractAdapter
57
+ def truncate_table(table_name)
58
+ execute("TRUNCATE #{quote_table_name(table_name)} IMMEDIATE")
59
+ end
60
+ end
61
+
62
+ class SQLite3Adapter < SQLITE_ADAPTER_PARENT
63
+ def delete_table(table_name)
64
+ execute("DELETE FROM #{quote_table_name(table_name)};")
65
+ execute("DELETE FROM sqlite_sequence where name = '#{table_name}';")
66
+ end
67
+ alias truncate_table delete_table
68
+ end
69
+
70
+ class JdbcAdapter < AbstractAdapter
71
+ def truncate_table(table_name)
72
+ begin
73
+ execute("TRUNCATE TABLE #{quote_table_name(table_name)};")
74
+ rescue ActiveRecord::StatementInvalid
75
+ execute("DELETE FROM #{quote_table_name(table_name)};")
76
+ end
77
+ end
78
+ end
79
+
80
+ class PostgreSQLAdapter < POSTGRE_ADAPTER_PARENT
81
+
82
+ def db_version
83
+ @db_version ||= postgresql_version
84
+ end
85
+
86
+ def cascade
87
+ @cascade ||= db_version >= 80200 ? 'CASCADE' : ''
88
+ end
89
+
90
+ def restart_identity
91
+ @restart_identity ||= db_version >= 80400 ? 'RESTART IDENTITY' : ''
92
+ end
93
+
94
+ def truncate_table(table_name)
95
+ truncate_tables([table_name])
96
+ end
97
+
98
+ def truncate_tables(table_names)
99
+ return if table_names.nil? || table_names.empty?
100
+ execute("TRUNCATE TABLE #{table_names.map{|name| quote_table_name(name)}.join(', ')} #{restart_identity} #{cascade};")
101
+ end
102
+
103
+ end
104
+
105
+ class SQLServerAdapter < AbstractAdapter
106
+ def truncate_table(table_name)
107
+ begin
108
+ execute("TRUNCATE TABLE #{quote_table_name(table_name)};")
109
+ rescue ActiveRecord::StatementInvalid
110
+ execute("DELETE FROM #{quote_table_name(table_name)};")
111
+ end
112
+ end
113
+ end
114
+
115
+ class OracleEnhancedAdapter < AbstractAdapter
116
+ def truncate_table(table_name)
117
+ execute("TRUNCATE TABLE #{quote_table_name(table_name)}")
118
+ end
119
+ end
120
+
121
+ end
122
+ end
123
+
124
+
125
+ module DatabaseCleaner::ActiveRecord
126
+ class Truncation
127
+ include ::DatabaseCleaner::ActiveRecord::Base
128
+ include ::DatabaseCleaner::Generic::Truncation
129
+
130
+ def clean
131
+ connection = connection_klass.connection
132
+ connection.disable_referential_integrity do
133
+ connection.truncate_tables(tables_to_truncate(connection))
134
+ end
135
+ end
136
+
137
+ private
138
+
139
+ def tables_to_truncate(connection)
140
+ (@only || connection.tables) - @tables_to_exclude - connection.views
141
+ end
142
+
143
+ # overwritten
144
+ def migration_storage_name
145
+ 'schema_migrations'
146
+ end
147
+
148
+ end
149
+ end
150
+
151
+
152
+
@@ -0,0 +1,138 @@
1
+ require 'database_cleaner/null_strategy'
2
+ module DatabaseCleaner
3
+ class Base
4
+
5
+ def initialize(desired_orm = nil,opts = {})
6
+ if [:autodetect, nil, "autodetect"].include?(desired_orm)
7
+ autodetect
8
+ else
9
+ self.orm = desired_orm
10
+ end
11
+ self.db = opts[:connection] if opts.has_key? :connection
12
+ set_default_orm_strategy
13
+ end
14
+
15
+ def db=(desired_db)
16
+ self.strategy_db = desired_db
17
+ @db = desired_db
18
+ end
19
+
20
+ def strategy_db=(desired_db)
21
+ if strategy.respond_to? :db=
22
+ strategy.db = desired_db
23
+ elsif desired_db!= :default
24
+ raise ArgumentError, "You must provide a strategy object that supports non default databases when you specify a database"
25
+ end
26
+ end
27
+
28
+ def db
29
+ @db || :default
30
+ end
31
+
32
+ def create_strategy(*args)
33
+ strategy, *strategy_args = args
34
+ orm_strategy(strategy).new(*strategy_args)
35
+ end
36
+
37
+ def clean_with(*args)
38
+ strategy = create_strategy(*args)
39
+ strategy.clean
40
+ strategy
41
+ end
42
+
43
+ alias clean_with! clean_with
44
+
45
+ def strategy=(args)
46
+ strategy, *strategy_args = args
47
+ if strategy.is_a?(Symbol)
48
+ @strategy = create_strategy(*args)
49
+ elsif strategy_args.empty?
50
+ @strategy = strategy
51
+ else
52
+ raise ArgumentError, "You must provide a strategy object, or a symbol for a known strategy along with initialization params."
53
+ end
54
+
55
+ self.strategy_db = self.db
56
+
57
+ @strategy
58
+ end
59
+
60
+ def strategy
61
+ @strategy || NullStrategy
62
+ end
63
+
64
+ def orm=(desired_orm)
65
+ @orm = desired_orm.to_sym
66
+ end
67
+
68
+ def orm
69
+ @orm || autodetect
70
+ end
71
+
72
+ def start
73
+ strategy.start
74
+ end
75
+
76
+ def clean
77
+ strategy.clean
78
+ end
79
+
80
+ alias clean! clean
81
+
82
+ def auto_detected?
83
+ !!@autodetected
84
+ end
85
+
86
+ #TODO make strategies directly comparable
87
+ def ==(other)
88
+ self.orm == other.orm && self.db == other.db && self.strategy.class == other.strategy.class
89
+ end
90
+
91
+ private
92
+
93
+ def orm_module
94
+ ::DatabaseCleaner.orm_module(orm)
95
+ end
96
+
97
+ def orm_strategy(strategy)
98
+ require "database_cleaner/#{orm.to_s}/#{strategy.to_s}"
99
+ orm_module.const_get(strategy.to_s.capitalize)
100
+ rescue LoadError => e
101
+ if orm_module.respond_to? :available_strategies
102
+ raise UnknownStrategySpecified, "The '#{strategy}' strategy does not exist for the #{orm} ORM! Available strategies: #{orm_module.available_strategies.join(', ')}"
103
+ else
104
+ raise UnknownStrategySpecified, "The '#{strategy}' strategy does not exist for the #{orm} ORM!"
105
+ end
106
+ end
107
+
108
+ def autodetect
109
+ @orm ||= begin
110
+ @autodetected = true
111
+ if defined? ::ActiveRecord
112
+ :active_record
113
+ elsif defined? ::DataMapper
114
+ :data_mapper
115
+ elsif defined? ::MongoMapper
116
+ :mongo_mapper
117
+ elsif defined? ::Mongoid
118
+ :mongoid
119
+ elsif defined? ::CouchPotato
120
+ :couch_potato
121
+ elsif defined? ::Sequel
122
+ :sequel
123
+ else
124
+ raise NoORMDetected, "No known ORM was detected! Is ActiveRecord, DataMapper, Sequel, MongoMapper, Mongoid, or CouchPotato loaded?"
125
+ end
126
+ end
127
+ end
128
+
129
+ def set_default_orm_strategy
130
+ case orm
131
+ when :active_record, :data_mapper, :sequel
132
+ self.strategy = :transaction
133
+ when :mongo_mapper, :mongoid, :couch_potato
134
+ self.strategy = :truncation
135
+ end
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,94 @@
1
+ require 'database_cleaner/base'
2
+
3
+ module DatabaseCleaner
4
+
5
+ class NoORMDetected < StandardError; end
6
+ class UnknownStrategySpecified < ArgumentError; end
7
+
8
+ class << self
9
+ def [](orm,opts = {})
10
+ raise NoORMDetected unless orm
11
+ @connections ||= []
12
+ cleaner = DatabaseCleaner::Base.new(orm,opts)
13
+ connections.push cleaner
14
+ cleaner
15
+ end
16
+
17
+ def app_root=(desired_root)
18
+ @app_root = desired_root
19
+ end
20
+
21
+ def app_root
22
+ @app_root || Dir.pwd
23
+ end
24
+
25
+ def connections
26
+ @connections ||= [::DatabaseCleaner::Base.new]
27
+ end
28
+
29
+ def logger=(log_source)
30
+ @logger = log_source
31
+ end
32
+
33
+ def logger
34
+ return @logger if @logger
35
+
36
+ @logger = Logger.new(STDOUT)
37
+ @logger.level = Logger::ERROR
38
+ @logger
39
+ end
40
+
41
+ def strategy=(stratagem)
42
+ connections.each { |connect| connect.strategy = stratagem }
43
+ remove_duplicates
44
+ end
45
+
46
+ def orm=(orm)
47
+ connections.each { |connect| connect.orm = orm }
48
+ remove_duplicates
49
+ end
50
+
51
+ def start
52
+ connections.each { |connection| connection.start }
53
+ end
54
+
55
+ def clean
56
+ connections.each { |connection| connection.clean }
57
+ end
58
+
59
+ alias clean! clean
60
+
61
+ def clean_with(*args)
62
+ connections.each { |connection| connection.clean_with(*args) }
63
+ end
64
+
65
+ alias clean_with! clean_with
66
+
67
+ def remove_duplicates
68
+ temp = []
69
+ connections.each do |connect|
70
+ temp.push connect unless temp.include? connect
71
+ end
72
+ @connections = temp
73
+ end
74
+
75
+ def orm_module(symbol)
76
+ case symbol
77
+ when :active_record
78
+ DatabaseCleaner::ActiveRecord
79
+ when :data_mapper
80
+ DatabaseCleaner::DataMapper
81
+ when :mongo
82
+ DatabaseCleaner::Mongo
83
+ when :mongoid
84
+ DatabaseCleaner::Mongoid
85
+ when :mongo_mapper
86
+ DatabaseCleaner::MongoMapper
87
+ when :couch_potato
88
+ DatabaseCleaner::CouchPotato
89
+ when :sequel
90
+ DatabaseCleaner::Sequel
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,7 @@
1
+ module DatabaseCleaner
2
+ module CouchPotato
3
+ def self.available_strategies
4
+ %w[truncation]
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,28 @@
1
+ require 'database_cleaner/generic/truncation'
2
+
3
+ module DatabaseCleaner
4
+ module CouchPotato
5
+ class Truncation
6
+ include ::DatabaseCleaner::Generic::Truncation
7
+
8
+ def initialize(options = {})
9
+ if options.has_key?(:only) || options.has_key?(:except)
10
+ raise ArgumentError, "The :only and :except options are not available for use with CouchPotato/CouchDB."
11
+ elsif !options.empty?
12
+ raise ArgumentError, "Unsupported option. You specified #{options.keys.join(',')}."
13
+ end
14
+ super
15
+ end
16
+
17
+ def clean
18
+ database.recreate!
19
+ end
20
+
21
+ private
22
+
23
+ def database
24
+ ::CouchPotato.couchrest_database
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,11 @@
1
+ Before do
2
+ DatabaseCleaner.start
3
+ end
4
+
5
+ After do
6
+ begin
7
+ DatabaseCleaner.clean
8
+ rescue Exception => e
9
+ DatabaseCleaner.logger.error "Exception encountered by DatabaseCleaner in Cucumber After block: #{e}"
10
+ end
11
+ end