surgical_strike 0.7.4

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 (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