database_cleaner 1.6.2 → 1.8.5

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 (170) hide show
  1. checksums.yaml +5 -5
  2. data/CONTRIBUTE.markdown +1 -2
  3. data/Gemfile.lock +132 -93
  4. data/History.rdoc +67 -0
  5. data/README.markdown +88 -217
  6. data/Rakefile +12 -8
  7. data/{lib → adapters/database_cleaner-active_record/lib}/database_cleaner/active_record/base.rb +14 -5
  8. data/{lib → adapters/database_cleaner-active_record/lib}/database_cleaner/active_record/deletion.rb +19 -17
  9. data/{lib → adapters/database_cleaner-active_record/lib}/database_cleaner/active_record/truncation.rb +25 -20
  10. data/adapters/database_cleaner-active_record/lib/database_cleaner/active_record/version.rb +5 -0
  11. data/adapters/database_cleaner-active_record/lib/database_cleaner/active_record.rb +6 -0
  12. data/adapters/database_cleaner-active_record/lib/database_cleaner-active_record.rb +1 -0
  13. data/adapters/database_cleaner-couch_potato/lib/database_cleaner/couch_potato/version.rb +5 -0
  14. data/adapters/database_cleaner-couch_potato/lib/database_cleaner/couch_potato.rb +11 -0
  15. data/adapters/database_cleaner-couch_potato/lib/database_cleaner-couch_potato.rb +1 -0
  16. data/{lib → adapters/database_cleaner-data_mapper/lib}/database_cleaner/data_mapper/base.rb +4 -0
  17. data/{lib → adapters/database_cleaner-data_mapper/lib}/database_cleaner/data_mapper/truncation.rb +4 -3
  18. data/adapters/database_cleaner-data_mapper/lib/database_cleaner/data_mapper/version.rb +5 -0
  19. data/adapters/database_cleaner-data_mapper/lib/database_cleaner/data_mapper.rb +4 -0
  20. data/adapters/database_cleaner-data_mapper/lib/database_cleaner-data_mapper.rb +1 -0
  21. data/{lib → adapters/database_cleaner-mongo/lib}/database_cleaner/mongo/truncation.rb +2 -0
  22. data/adapters/database_cleaner-mongo/lib/database_cleaner/mongo/version.rb +5 -0
  23. data/adapters/database_cleaner-mongo/lib/database_cleaner/mongo.rb +10 -0
  24. data/adapters/database_cleaner-mongo/lib/database_cleaner-mongo.rb +1 -0
  25. data/{lib → adapters/database_cleaner-mongo_mapper/lib}/database_cleaner/mongo_mapper/base.rb +4 -0
  26. data/adapters/database_cleaner-mongo_mapper/lib/database_cleaner/mongo_mapper/truncation.rb +35 -0
  27. data/adapters/database_cleaner-mongo_mapper/lib/database_cleaner/mongo_mapper/version.rb +5 -0
  28. data/adapters/database_cleaner-mongo_mapper/lib/database_cleaner/mongo_mapper.rb +4 -0
  29. data/adapters/database_cleaner-mongo_mapper/lib/database_cleaner-mongo_mapper.rb +1 -0
  30. data/adapters/database_cleaner-mongoid/lib/database_cleaner/mongoid/mongo1_truncation_mixin.rb +26 -0
  31. data/{lib/database_cleaner/mongo2/truncation_mixin.rb → adapters/database_cleaner-mongoid/lib/database_cleaner/mongoid/mongo2_truncation_mixin.rb} +3 -4
  32. data/adapters/database_cleaner-mongoid/lib/database_cleaner/mongoid/mongoid_truncation_mixin.rb +65 -0
  33. data/{lib → adapters/database_cleaner-mongoid/lib}/database_cleaner/mongoid/truncation.rb +6 -6
  34. data/adapters/database_cleaner-mongoid/lib/database_cleaner/mongoid/version.rb +5 -0
  35. data/adapters/database_cleaner-mongoid/lib/database_cleaner/mongoid.rb +10 -0
  36. data/adapters/database_cleaner-mongoid/lib/database_cleaner-mongoid.rb +1 -0
  37. data/{lib → adapters/database_cleaner-moped/lib}/database_cleaner/moped/base.rb +1 -1
  38. data/{lib → adapters/database_cleaner-moped/lib}/database_cleaner/moped/truncation_base.rb +4 -0
  39. data/adapters/database_cleaner-moped/lib/database_cleaner/moped/version.rb +5 -0
  40. data/adapters/database_cleaner-moped/lib/database_cleaner/moped.rb +10 -0
  41. data/adapters/database_cleaner-moped/lib/database_cleaner-moped.rb +1 -0
  42. data/{lib → adapters/database_cleaner-neo4j/lib}/database_cleaner/neo4j/base.rb +4 -0
  43. data/adapters/database_cleaner-neo4j/lib/database_cleaner/neo4j/version.rb +5 -0
  44. data/adapters/database_cleaner-neo4j/lib/database_cleaner/neo4j.rb +6 -0
  45. data/adapters/database_cleaner-neo4j/lib/database_cleaner-neo4j.rb +1 -0
  46. data/adapters/database_cleaner-ohm/lib/database_cleaner/ohm/truncation.rb +24 -0
  47. data/adapters/database_cleaner-ohm/lib/database_cleaner/ohm/version.rb +5 -0
  48. data/adapters/database_cleaner-ohm/lib/database_cleaner/ohm.rb +12 -0
  49. data/adapters/database_cleaner-ohm/lib/database_cleaner-ohm.rb +1 -0
  50. data/{lib → adapters/database_cleaner-redis/lib}/database_cleaner/redis/base.rb +4 -0
  51. data/adapters/database_cleaner-redis/lib/database_cleaner/redis/version.rb +5 -0
  52. data/adapters/database_cleaner-redis/lib/database_cleaner/redis.rb +4 -0
  53. data/adapters/database_cleaner-redis/lib/database_cleaner-redis.rb +1 -0
  54. data/{lib → adapters/database_cleaner-sequel/lib}/database_cleaner/sequel/base.rb +4 -0
  55. data/{lib → adapters/database_cleaner-sequel/lib}/database_cleaner/sequel/truncation.rb +16 -15
  56. data/adapters/database_cleaner-sequel/lib/database_cleaner/sequel/version.rb +5 -0
  57. data/adapters/database_cleaner-sequel/lib/database_cleaner/sequel.rb +6 -0
  58. data/adapters/database_cleaner-sequel/lib/database_cleaner-sequel.rb +1 -0
  59. data/lib/database_cleaner/base.rb +94 -105
  60. data/lib/database_cleaner/configuration.rb +87 -83
  61. data/lib/database_cleaner/deprecation.rb +26 -0
  62. data/lib/database_cleaner/null_strategy.rb +6 -6
  63. data/lib/database_cleaner/orm_autodetector.rb +41 -0
  64. data/lib/database_cleaner/safeguard.rb +107 -0
  65. data/lib/database_cleaner/spec/database_helper.rb +82 -0
  66. data/lib/database_cleaner/spec/shared_examples.rb +15 -0
  67. data/lib/database_cleaner/spec.rb +2 -0
  68. data/lib/database_cleaner/version.rb +3 -0
  69. data/lib/database_cleaner.rb +41 -2
  70. metadata +113 -126
  71. data/VERSION.yml +0 -4
  72. data/examples/Gemfile +0 -1
  73. data/examples/Gemfile.lock +0 -1
  74. data/examples/config/database.yml.example +0 -8
  75. data/examples/config/redis.yml +0 -8
  76. data/examples/db/sqlite_databases_go_here +0 -0
  77. data/examples/features/example.feature +0 -11
  78. data/examples/features/example_multiple_db.feature +0 -23
  79. data/examples/features/example_multiple_orm.feature +0 -22
  80. data/examples/features/step_definitions/activerecord_steps.rb +0 -31
  81. data/examples/features/step_definitions/couchpotato_steps.rb +0 -31
  82. data/examples/features/step_definitions/datamapper_steps.rb +0 -37
  83. data/examples/features/step_definitions/mongoid_steps.rb +0 -23
  84. data/examples/features/step_definitions/mongomapper_steps.rb +0 -31
  85. data/examples/features/step_definitions/neo4j_steps.rb +0 -23
  86. data/examples/features/step_definitions/ohm_steps.rb +0 -31
  87. data/examples/features/step_definitions/redis_steps.rb +0 -31
  88. data/examples/features/step_definitions/translation_steps.rb +0 -55
  89. data/examples/features/support/env.rb +0 -61
  90. data/examples/lib/activerecord_models.rb +0 -41
  91. data/examples/lib/couchpotato_models.rb +0 -61
  92. data/examples/lib/datamapper_models.rb +0 -50
  93. data/examples/lib/mongoid_models.rb +0 -44
  94. data/examples/lib/mongomapper_models.rb +0 -51
  95. data/examples/lib/neo4j_models.rb +0 -17
  96. data/examples/lib/ohm_models.rb +0 -43
  97. data/examples/lib/redis_models.rb +0 -65
  98. data/examples/lib/sequel_models.rb +0 -9
  99. data/features/cleaning.feature +0 -30
  100. data/features/cleaning_default_strategy.feature +0 -23
  101. data/features/cleaning_multiple_dbs.feature +0 -22
  102. data/features/cleaning_multiple_orms.feature +0 -67
  103. data/features/step_definitions/database_cleaner_steps.rb +0 -33
  104. data/features/support/env.rb +0 -4
  105. data/features/support/feature_runner.rb +0 -39
  106. data/lib/database_cleaner/mongo2/base.rb +0 -16
  107. data/lib/database_cleaner/mongo_mapper/truncation.rb +0 -19
  108. data/lib/database_cleaner/ohm/truncation.rb +0 -15
  109. data/spec/database_cleaner/active_record/base_spec.rb +0 -188
  110. data/spec/database_cleaner/active_record/transaction_spec.rb +0 -176
  111. data/spec/database_cleaner/active_record/truncation/mysql2_spec.rb +0 -38
  112. data/spec/database_cleaner/active_record/truncation/mysql_spec.rb +0 -38
  113. data/spec/database_cleaner/active_record/truncation/postgresql_spec.rb +0 -75
  114. data/spec/database_cleaner/active_record/truncation/shared_fast_truncation.rb +0 -40
  115. data/spec/database_cleaner/active_record/truncation/sqlite3_spec.rb +0 -40
  116. data/spec/database_cleaner/active_record/truncation_spec.rb +0 -180
  117. data/spec/database_cleaner/base_spec.rb +0 -617
  118. data/spec/database_cleaner/configuration_spec.rb +0 -345
  119. data/spec/database_cleaner/couch_potato/truncation_spec.rb +0 -41
  120. data/spec/database_cleaner/data_mapper/base_spec.rb +0 -30
  121. data/spec/database_cleaner/data_mapper/transaction_spec.rb +0 -23
  122. data/spec/database_cleaner/data_mapper/truncation/sqlite3_spec.rb +0 -41
  123. data/spec/database_cleaner/data_mapper/truncation_spec.rb +0 -11
  124. data/spec/database_cleaner/generic/base_spec.rb +0 -61
  125. data/spec/database_cleaner/generic/truncation_spec.rb +0 -118
  126. data/spec/database_cleaner/mongo/mongo_examples.rb +0 -26
  127. data/spec/database_cleaner/mongo/truncation_spec.rb +0 -72
  128. data/spec/database_cleaner/mongo_mapper/base_spec.rb +0 -33
  129. data/spec/database_cleaner/mongo_mapper/mongo_examples.rb +0 -8
  130. data/spec/database_cleaner/mongo_mapper/truncation_spec.rb +0 -74
  131. data/spec/database_cleaner/moped/moped_examples.rb +0 -32
  132. data/spec/database_cleaner/moped/truncation_spec.rb +0 -80
  133. data/spec/database_cleaner/neo4j/base_spec.rb +0 -43
  134. data/spec/database_cleaner/neo4j/transaction_spec.rb +0 -25
  135. data/spec/database_cleaner/null_strategy_spec.rb +0 -28
  136. data/spec/database_cleaner/ohm/truncation_spec.rb +0 -70
  137. data/spec/database_cleaner/redis/base_spec.rb +0 -43
  138. data/spec/database_cleaner/redis/truncation_spec.rb +0 -63
  139. data/spec/database_cleaner/sequel/base_spec.rb +0 -32
  140. data/spec/database_cleaner/sequel/deletion_spec.rb +0 -58
  141. data/spec/database_cleaner/sequel/transaction_spec.rb +0 -21
  142. data/spec/database_cleaner/sequel/truncation/sqlite3_spec.rb +0 -0
  143. data/spec/database_cleaner/sequel/truncation_spec.rb +0 -182
  144. data/spec/database_cleaner/shared_strategy.rb +0 -15
  145. data/spec/rcov.opts +0 -1
  146. data/spec/spec_helper.rb +0 -21
  147. data/spec/support/active_record/database_setup.rb +0 -6
  148. data/spec/support/active_record/migrations/20150101010000_create_users.rb +0 -14
  149. data/spec/support/active_record/migrations/20150101020000_create_agents.rb +0 -14
  150. data/spec/support/active_record/mysql2_setup.rb +0 -39
  151. data/spec/support/active_record/mysql_setup.rb +0 -38
  152. data/spec/support/active_record/postgresql_setup.rb +0 -48
  153. data/spec/support/active_record/schema_setup.rb +0 -17
  154. data/spec/support/active_record/sqlite3_setup.rb +0 -40
  155. data/spec/support/data_mapper/schema_setup.rb +0 -15
  156. data/spec/support/data_mapper/sqlite3_setup.rb +0 -39
  157. /data/{lib → adapters/database_cleaner-active_record/lib}/database_cleaner/active_record/transaction.rb +0 -0
  158. /data/{lib → adapters/database_cleaner-couch_potato/lib}/database_cleaner/couch_potato/base.rb +0 -0
  159. /data/{lib → adapters/database_cleaner-couch_potato/lib}/database_cleaner/couch_potato/truncation.rb +0 -0
  160. /data/{lib → adapters/database_cleaner-data_mapper/lib}/database_cleaner/data_mapper/transaction.rb +0 -0
  161. /data/{lib → adapters/database_cleaner-mongo/lib}/database_cleaner/mongo/base.rb +0 -0
  162. /data/{lib → adapters/database_cleaner-mongo/lib}/database_cleaner/mongo/truncation_mixin.rb +0 -0
  163. /data/{lib → adapters/database_cleaner-mongoid/lib}/database_cleaner/mongoid/base.rb +0 -0
  164. /data/{lib → adapters/database_cleaner-moped/lib}/database_cleaner/moped/truncation.rb +0 -0
  165. /data/{lib → adapters/database_cleaner-neo4j/lib}/database_cleaner/neo4j/deletion.rb +0 -0
  166. /data/{lib → adapters/database_cleaner-neo4j/lib}/database_cleaner/neo4j/transaction.rb +0 -0
  167. /data/{lib → adapters/database_cleaner-neo4j/lib}/database_cleaner/neo4j/truncation.rb +0 -0
  168. /data/{lib → adapters/database_cleaner-redis/lib}/database_cleaner/redis/truncation.rb +0 -0
  169. /data/{lib → adapters/database_cleaner-sequel/lib}/database_cleaner/sequel/deletion.rb +0 -0
  170. /data/{lib → adapters/database_cleaner-sequel/lib}/database_cleaner/sequel/transaction.rb +0 -0
@@ -1,164 +1,153 @@
1
+ require 'database_cleaner/deprecation'
1
2
  require 'database_cleaner/null_strategy'
3
+ require 'database_cleaner/safeguard'
4
+ require 'database_cleaner/orm_autodetector'
5
+ require 'forwardable'
6
+
2
7
  module DatabaseCleaner
3
8
  class Base
4
9
  include Comparable
5
10
 
6
11
  def <=>(other)
7
- (self.orm <=> other.orm) == 0 ? self.db <=> other.db : self.orm <=> other.orm
12
+ [orm, db] <=> [other.orm, other.db]
8
13
  end
9
14
 
10
- def initialize(desired_orm = nil,opts = {})
11
- if [:autodetect, nil, "autodetect"].include?(desired_orm)
12
- autodetect
13
- else
14
- self.orm = desired_orm
15
- end
15
+ def initialize(desired_orm = nil, opts = {})
16
+ @orm_autodetector = ORMAutodetector.new
17
+ self.orm = desired_orm
16
18
  self.db = opts[:connection] || opts[:model] if opts.has_key?(:connection) || opts.has_key?(:model)
17
- set_default_orm_strategy
19
+ self.strategy = orm_module && orm_module.default_strategy
20
+ Safeguard.new.run
18
21
  end
19
22
 
20
23
  def db=(desired_db)
21
- self.strategy_db = desired_db
22
- @db = desired_db
23
- end
24
-
25
- def strategy_db=(desired_db)
26
- if strategy.respond_to? :db=
27
- strategy.db = desired_db
28
- elsif desired_db!= :default
29
- raise ArgumentError, "You must provide a strategy object that supports non default databases when you specify a database"
30
- end
24
+ @db = self.strategy_db = desired_db
31
25
  end
32
26
 
33
27
  def db
34
28
  @db ||= :default
35
29
  end
36
30
 
37
- def create_strategy(*args)
31
+ def strategy=(args)
38
32
  strategy, *strategy_args = args
39
- orm_strategy(strategy).new(*strategy_args)
40
- end
33
+ @strategy = if strategy.is_a?(Symbol)
34
+ create_strategy(*args)
35
+ elsif strategy_args.empty?
36
+ strategy
37
+ else
38
+ raise ArgumentError, "You must provide a strategy object, or a symbol for a known strategy along with initialization params."
39
+ end
41
40
 
42
- def clean_with(*args)
43
- strategy = create_strategy(*args)
44
- set_strategy_db strategy, self.db
41
+ set_strategy_db @strategy, db
42
+ end
45
43
 
46
- strategy.clean
47
- strategy
44
+ def strategy
45
+ @strategy ||= NullStrategy.new
48
46
  end
49
47
 
50
- alias clean_with! clean_with
48
+ attr_reader :orm
51
49
 
52
- def set_strategy_db(strategy, desired_db)
53
- if strategy.respond_to? :db=
54
- strategy.db = desired_db
55
- elsif desired_db != :default
56
- raise ArgumentError, "You must provide a strategy object that supports non default databases when you specify a database"
57
- end
50
+ def orm=(desired_orm)
51
+ @orm = (desired_orm || :autodetect).to_sym
52
+ @orm = @orm_autodetector.orm if @orm == :autodetect
58
53
  end
59
54
 
60
- def strategy=(args)
61
- strategy, *strategy_args = args
62
- if strategy.is_a?(Symbol)
63
- @strategy = create_strategy(*args)
64
- elsif strategy_args.empty?
65
- @strategy = strategy
66
- else
67
- raise ArgumentError, "You must provide a strategy object, or a symbol for a known strategy along with initialization params."
68
- end
55
+ extend Forwardable
56
+ delegate [:start, :clean, :cleaning] => :strategy
69
57
 
70
- set_strategy_db @strategy, self.db
71
-
72
- @strategy
58
+ def clean_with(*args)
59
+ strategy = create_strategy(*args)
60
+ set_strategy_db strategy, db
61
+ strategy.clean
62
+ strategy
73
63
  end
74
64
 
75
- def strategy
76
- @strategy ||= NullStrategy
77
- end
65
+ # TODO remove the following methods in 2.0
78
66
 
79
- def orm=(desired_orm)
80
- @orm = desired_orm.to_sym
67
+ def auto_detected?
68
+ DatabaseCleaner.deprecate "Calling `DatabaseCleaner[...].auto_detected?` is deprecated, and will be removed in database_cleaner 2.0 with no replacement."
69
+ @orm_autodetector.autodetected?
81
70
  end
82
71
 
83
- def orm
84
- @orm || autodetect
72
+ def autodetect_orm
73
+ DatabaseCleaner.deprecate "Calling `DatabaseCleaner[...].autodetect_orm` is deprecated, and will be removed in database_cleaner 2.0 with no replacement."
74
+ @orm_autodetector.orm
85
75
  end
86
76
 
87
- def start
88
- strategy.start
77
+ def clean!
78
+ DatabaseCleaner.deprecate "Calling `DatabaseCleaner[...].clean!` is deprecated, and will be removed in database_cleaner 2.0. Use `DatabaseCleaner[...].clean instead."
79
+ clean
89
80
  end
90
81
 
91
- def clean
92
- strategy.clean
82
+ def clean_with!
83
+ DatabaseCleaner.deprecate "Calling `DatabaseCleaner[...].clean_with!` is deprecated, and will be removed in database_cleaner 2.0. Use `DatabaseCleaner[...].clean_with instead."
84
+ clean_with
93
85
  end
94
86
 
95
- alias clean! clean
87
+ # TODO privatize the following methods in 2.0
96
88
 
97
- def cleaning(&block)
98
- strategy.cleaning(&block)
89
+ def strategy_db=(desired_db)
90
+ if DatabaseCleaner.called_externally?(__FILE__, caller)
91
+ DatabaseCleaner.deprecate "Calling `DatabaseCleaner[...].strategy_db=` is deprecated, and will be removed in database_cleaner 2.0. Use `DatabaseCleaner[...].db=` instead."
92
+ end
93
+ set_strategy_db(strategy, desired_db)
99
94
  end
100
95
 
101
- def auto_detected?
102
- !!@autodetected
96
+ def set_strategy_db(strategy, desired_db)
97
+ if DatabaseCleaner.called_externally?(__FILE__, caller)
98
+ DatabaseCleaner.deprecate "Calling `DatabaseCleaner[...].set_strategy_db=` is deprecated, and will be removed in database_cleaner 2.0. Use `DatabaseCleaner[...].db=` instead."
99
+ end
100
+ if strategy.respond_to? :db=
101
+ strategy.db = desired_db
102
+ elsif desired_db != :default
103
+ raise ArgumentError, "You must provide a strategy object that supports non default databases when you specify a database"
104
+ end
103
105
  end
104
106
 
105
- def autodetect_orm
106
- if defined? ::ActiveRecord
107
- :active_record
108
- elsif defined? ::DataMapper
109
- :data_mapper
110
- elsif defined? ::MongoMapper
111
- :mongo_mapper
112
- elsif defined? ::Mongoid
113
- :mongoid
114
- elsif defined? ::CouchPotato
115
- :couch_potato
116
- elsif defined? ::Sequel
117
- :sequel
118
- elsif defined? ::Moped
119
- :moped
120
- elsif defined? ::Ohm
121
- :ohm
122
- elsif defined? ::Redis
123
- :redis
124
- elsif defined? ::Neo4j
125
- :neo4j
107
+ def create_strategy(*args)
108
+ if DatabaseCleaner.called_externally?(__FILE__, caller)
109
+ DatabaseCleaner.deprecate "Calling `DatabaseCleaner[...].create_strategy` is deprecated, and will be removed in database_cleaner 2.0. Use `DatabaseCleaner[...].strategy=` instead."
126
110
  end
111
+ strategy, *strategy_args = args
112
+ orm_strategy(strategy).new(*strategy_args)
127
113
  end
128
114
 
129
115
  private
130
116
 
131
117
  def orm_module
132
- ::DatabaseCleaner.orm_module(orm)
118
+ return unless [:active_record, :data_mapper, :mongo, :mongoid, :mongo_mapper, :moped, :couch_potato, :sequel, :ohm, :redis, :neo4j].include?(orm)
119
+ load_adapter(orm) if !adapter_loaded?(orm)
120
+ orm_module_name = ORMAutodetector::ORMS[orm]
121
+ DatabaseCleaner.const_get(orm_module_name, false)
133
122
  end
134
123
 
135
- def orm_strategy(strategy)
136
- require "database_cleaner/#{orm.to_s}/#{strategy.to_s}"
137
- orm_module.const_get(strategy.to_s.capitalize)
138
- rescue LoadError
139
- if orm_module.respond_to? :available_strategies
140
- raise UnknownStrategySpecified, "The '#{strategy}' strategy does not exist for the #{orm} ORM! Available strategies: #{orm_module.available_strategies.join(', ')}"
141
- else
142
- raise UnknownStrategySpecified, "The '#{strategy}' strategy does not exist for the #{orm} ORM!"
143
- end
124
+ def adapter_loaded? orm
125
+ $LOADED_FEATURES.grep(%r{/lib/database_cleaner/#{orm}\.rb$}).any?
144
126
  end
145
127
 
146
- def autodetect
147
- @autodetected = true
148
-
149
- @orm ||= autodetect_orm ||
150
- raise(NoORMDetected, "No known ORM was detected! Is ActiveRecord, DataMapper, Sequel, MongoMapper, Mongoid, Moped, or CouchPotato, Redis or Ohm loaded?")
128
+ def load_adapter orm
129
+ $LOAD_PATH.unshift File.expand_path("#{File.dirname(__FILE__)}/../../adapters/database_cleaner-#{orm}/lib")
130
+ require "database_cleaner/#{orm}"
151
131
  end
152
132
 
153
- def set_default_orm_strategy
154
- case orm
155
- when :active_record, :data_mapper, :sequel
156
- self.strategy = :transaction
157
- when :mongo_mapper, :mongoid, :couch_potato, :moped, :ohm, :redis
158
- self.strategy = :truncation
159
- when :neo4j
160
- self.strategy = :transaction
133
+ def orm_strategy(strategy)
134
+ strategy_module_name = strategy.to_s.capitalize
135
+ orm_module.const_get(strategy_module_name, false)
136
+ rescue NameError
137
+ if orm != :active_record
138
+ DatabaseCleaner.deprecate <<-TEXT
139
+ The #{orm_module} adapter has been extracted to its own gem: database_cleaner-#{orm}, and will be removed from database_cleaner in 2.0. To silence this message, please replace `gem "database_cleaner"` with `gem "database_cleaner-#{orm}"` in your Gemfile.
140
+ TEXT
161
141
  end
142
+ require_orm_strategy(orm, strategy)
143
+ retry
144
+ end
145
+
146
+ def require_orm_strategy(orm, strategy)
147
+ $LOAD_PATH.unshift File.expand_path("#{File.dirname(__FILE__)}/../../adapters/database_cleaner-#{orm}/lib")
148
+ require "database_cleaner/#{orm}/#{strategy}"
149
+ rescue LoadError
150
+ raise UnknownStrategySpecified, "The '#{strategy}' strategy does not exist for the #{orm} ORM! Available strategies: #{orm_module.available_strategies.join(', ')}"
162
151
  end
163
152
  end
164
153
  end
@@ -1,74 +1,77 @@
1
1
  require 'database_cleaner/base'
2
+ require 'database_cleaner/deprecation'
3
+ require 'forwardable'
2
4
 
3
5
  module DatabaseCleaner
4
6
 
5
- class NoORMDetected < StandardError; end
6
- class UnknownStrategySpecified < ArgumentError; end
7
+ class NoORMDetected < StandardError; end
8
+ class UnknownStrategySpecified < ArgumentError; end
7
9
 
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
-
15
- def [](orm,opts = {})
10
+ class Cleaners < Hash
11
+ # FIXME this method conflates creation with lookup... both a command and a query. yuck.
12
+ def [](orm, opts = {})
16
13
  raise NoORMDetected unless orm
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
14
+ fetch([orm, opts]) { add_cleaner(orm, opts) }
15
+ end
26
16
 
27
- def add_cleaner(orm,opts = {})
28
- init_cleaners
29
- cleaner = DatabaseCleaner::Base.new(orm,opts)
30
- @cleaners[[orm, opts]] = cleaner
31
- @connections << cleaner
32
- cleaner
17
+ def strategy=(strategy)
18
+ add_cleaner(:autodetect) if none?
19
+ values.each { |cleaner| cleaner.strategy = strategy }
20
+ remove_duplicates
33
21
  end
34
22
 
35
- def app_root=(desired_root)
36
- @app_root = desired_root
23
+ def orm=(orm)
24
+ add_cleaner(:autodetect) if none?
25
+ values.each { |cleaner| cleaner.orm = orm }
26
+ remove_duplicates
37
27
  end
38
28
 
39
- def app_root
40
- @app_root ||= Dir.pwd
29
+ # TODO privatize the following methods in 2.0
30
+
31
+ def add_cleaner(orm, opts = {})
32
+ self[[orm, opts]] = ::DatabaseCleaner::Base.new(orm, opts)
41
33
  end
42
34
 
43
- def connections
44
- # double yuck.. can't wait to deprecate this whole class...
45
- unless defined?(@cleaners) && @cleaners
46
- autodetected = ::DatabaseCleaner::Base.new
47
- add_cleaner(autodetected.orm)
48
- end
49
- @connections
35
+ def remove_duplicates
36
+ replace(reduce(Cleaners.new) do |cleaners, (key, value)|
37
+ cleaners[key] = value unless cleaners.values.include?(value)
38
+ cleaners
39
+ end)
50
40
  end
41
+ end
51
42
 
52
- def logger=(log_source)
53
- @logger = log_source
43
+ class Configuration
44
+ def initialize
45
+ @cleaners ||= Cleaners.new
54
46
  end
55
47
 
56
- def logger
57
- return @logger if @logger
48
+ extend Forwardable
49
+ delegate [
50
+ :[],
51
+ :strategy=,
52
+ :orm=,
53
+ ] => :cleaners
58
54
 
59
- @logger = Logger.new(STDOUT)
60
- @logger.level = Logger::ERROR
61
- @logger
55
+ attr_accessor :cleaners
56
+
57
+ def app_root
58
+ DatabaseCleaner.deprecate "Calling `DatabaseCleaner.app_root` is deprecated, and will be removed in database_cleaner 2.0. Use `DatabaseCleaner::ActiveRecord.config_file_location`, instead."
59
+ @app_root ||= Dir.pwd
62
60
  end
63
61
 
64
- def strategy=(stratagem)
65
- connections.each { |connect| connect.strategy = stratagem }
66
- remove_duplicates
62
+ def app_root= value
63
+ DatabaseCleaner.deprecate "Calling `DatabaseCleaner.app_root=` is deprecated, and will be removed in database_cleaner 2.0. Use `DatabaseCleaner::ActiveRecord.config_file_location=`, instead."
64
+ @app_root = value
67
65
  end
68
66
 
69
- def orm=(orm)
70
- connections.each { |connect| connect.orm = orm }
71
- remove_duplicates
67
+ def logger
68
+ DatabaseCleaner.deprecate "Calling `DatabaseCleaner.logger` is deprecated, and will be removed in database_cleaner 2.0 with no replacement."
69
+ @logger ||= Logger.new(STDOUT).tap { |l| l.level = Logger::ERROR }
70
+ end
71
+
72
+ def logger= value
73
+ DatabaseCleaner.deprecate "Calling `DatabaseCleaner.logger=` is deprecated, and will be removed in database_cleaner 2.0 with no replacement."
74
+ @logger = value
72
75
  end
73
76
 
74
77
  def start
@@ -79,8 +82,6 @@ module DatabaseCleaner
79
82
  connections.each { |connection| connection.clean }
80
83
  end
81
84
 
82
- alias clean! clean
83
-
84
85
  def cleaning(&inner_block)
85
86
  connections.inject(inner_block) do |curr_block, connection|
86
87
  proc { connection.cleaning(&curr_block) }
@@ -91,41 +92,44 @@ module DatabaseCleaner
91
92
  connections.each { |connection| connection.clean_with(*args) }
92
93
  end
93
94
 
94
- alias clean_with! clean_with
95
+ # TODO remove the following methods in 2.0
95
96
 
96
- def remove_duplicates
97
- temp = []
98
- connections.each do |connect|
99
- temp.push connect unless temp.include? connect
97
+ def clean!
98
+ DatabaseCleaner.deprecate "Calling `DatabaseCleaner.clean!` is deprecated, and will be removed in database_cleaner 2.0. Use `DatabaseCleaner.clean`, instead."
99
+ clean
100
+ end
101
+
102
+ def clean_with!(*args)
103
+ DatabaseCleaner.deprecate "Calling `DatabaseCleaner.clean_with!` is deprecated, and will be removed in database_cleaner 2.0. Use `DatabaseCleaner.clean_with`, instead."
104
+ clean_with(*args)
105
+ end
106
+
107
+ def init_cleaners
108
+ DatabaseCleaner.deprecate "Calling `DatabaseCleaner.init_cleaners` is deprecated, and will be removed in database_cleaner 2.0 with no replacement."
109
+ end
110
+
111
+ def connections
112
+ if DatabaseCleaner.called_externally?(__FILE__, caller)
113
+ DatabaseCleaner.deprecate "Calling `DatabaseCleaner.connections` is deprecated, and will be removed in database_cleaner 2.0. Use `DatabaseCleaner.cleaners`, instead."
114
+ end
115
+ add_cleaner(:autodetect) if @cleaners.none?
116
+ @cleaners.values
117
+ end
118
+
119
+ # TODO privatize the following methods in 2.0
120
+
121
+ def add_cleaner(orm, opts = {})
122
+ if DatabaseCleaner.called_externally?(__FILE__, caller)
123
+ DatabaseCleaner.deprecate "Calling `DatabaseCleaner.add_cleaner` is deprecated, and will be removed in database_cleaner 2.0. Use `DatabaseCleaner.[]`, instead."
100
124
  end
101
- @connections = temp
102
- end
103
-
104
- def orm_module(symbol)
105
- case symbol
106
- when :active_record
107
- DatabaseCleaner::ActiveRecord
108
- when :data_mapper
109
- DatabaseCleaner::DataMapper
110
- when :mongo
111
- DatabaseCleaner::Mongo
112
- when :mongoid
113
- DatabaseCleaner::Mongoid
114
- when :mongo_mapper
115
- DatabaseCleaner::MongoMapper
116
- when :moped
117
- DatabaseCleaner::Moped
118
- when :couch_potato
119
- DatabaseCleaner::CouchPotato
120
- when :sequel
121
- DatabaseCleaner::Sequel
122
- when :ohm
123
- DatabaseCleaner::Ohm
124
- when :redis
125
- DatabaseCleaner::Redis
126
- when :neo4j
127
- DatabaseCleaner::Neo4j
125
+ @cleaners.add_cleaner(orm, opts = {})
126
+ end
127
+
128
+ def remove_duplicates
129
+ if DatabaseCleaner.called_externally?(__FILE__, caller)
130
+ DatabaseCleaner.deprecate "Calling `DatabaseCleaner.remove_duplicates` is deprecated, and will be removed in database_cleaner 2.0 with no replacement."
128
131
  end
132
+ @cleaners.remove_duplicates
129
133
  end
130
134
  end
131
135
  end
@@ -0,0 +1,26 @@
1
+ module DatabaseCleaner
2
+ def deprecate message
3
+ method = caller.first[/\d+:in `(.*)'$/, 1].to_sym
4
+ @@deprecator ||= Deprecator.new
5
+ @@deprecator.deprecate method, message
6
+ end
7
+ module_function :deprecate
8
+
9
+ def called_externally?(file, caller)
10
+ file != caller.first[/^(.+\.rb):\d+/, 1]
11
+ end
12
+ module_function :called_externally?
13
+
14
+ class Deprecator
15
+ def initialize
16
+ @methods_already_warned = {}
17
+ end
18
+
19
+ def deprecate method, message
20
+ return if @methods_already_warned.key?(method)
21
+ $stderr.puts message
22
+ @methods_already_warned[method] = true
23
+ end
24
+ end
25
+ end
26
+
@@ -1,18 +1,18 @@
1
1
  module DatabaseCleaner
2
2
  class NullStrategy
3
- def self.start
3
+ def start
4
4
  # no-op
5
5
  end
6
6
 
7
- def self.db=(connection)
8
- # no-op
9
- end
7
+ def db=(connection)
8
+ # no-op
9
+ end
10
10
 
11
- def self.clean
11
+ def clean
12
12
  # no-op
13
13
  end
14
14
 
15
- def self.cleaning(&block)
15
+ def cleaning(&block)
16
16
  # no-op
17
17
  yield
18
18
  end
@@ -0,0 +1,41 @@
1
+ module DatabaseCleaner
2
+ class ORMAutodetector
3
+ ORMS = {
4
+ active_record: "ActiveRecord",
5
+ data_mapper: "DataMapper",
6
+ mongo_mapper: "MongoMapper",
7
+ mongoid: "Mongoid",
8
+ mongo: "Mongo",
9
+ couch_potato: "CouchPotato",
10
+ sequel: "Sequel",
11
+ moped: "Moped",
12
+ ohm: "Ohm",
13
+ redis: "Redis",
14
+ neo4j: "Neo4j",
15
+ }
16
+
17
+ def orm
18
+ @autodetected = true
19
+ autodetected_orm or raise no_orm_detected_error
20
+ ORMS.key(autodetected_orm.to_s)
21
+ end
22
+
23
+ def autodetected?
24
+ !!@autodetected
25
+ end
26
+
27
+ private
28
+
29
+ def autodetected_orm
30
+ ORMS.values.find do |orm|
31
+ Kernel.const_get(orm) rescue next
32
+ end
33
+ end
34
+
35
+ def no_orm_detected_error
36
+ orm_list = ORMS.values.join(", ").sub(ORMS.values.last, "or #{ORMS.values.last}")
37
+ NoORMDetected.new("No known ORM was detected! Is #{orm_list} loaded?")
38
+ end
39
+ end
40
+ private_constant :ORMAutodetector
41
+ end
@@ -0,0 +1,107 @@
1
+ module DatabaseCleaner
2
+ class Safeguard
3
+ class Error < Exception
4
+ class RemoteDatabaseUrl < Error
5
+ def initialize
6
+ super("ENV['DATABASE_URL'] is set to a remote URL. Please refer to https://github.com/DatabaseCleaner/database_cleaner#safeguards")
7
+ end
8
+ end
9
+
10
+ class ProductionEnv < Error
11
+ def initialize(env)
12
+ super("ENV['#{env}'] is set to production. Please refer to https://github.com/DatabaseCleaner/database_cleaner#safeguards")
13
+ end
14
+ end
15
+
16
+ class NotWhitelistedUrl < Error
17
+ def initialize
18
+ super("ENV['DATABASE_URL'] is set to a URL that is not on the whitelist. Please refer to https://github.com/DatabaseCleaner/database_cleaner#safeguards")
19
+ end
20
+ end
21
+ end
22
+
23
+ class WhitelistedUrl
24
+ def run
25
+ return if skip?
26
+ raise Error::NotWhitelistedUrl if database_url_not_whitelisted?
27
+ end
28
+
29
+ private
30
+
31
+ def database_url_not_whitelisted?
32
+ !DatabaseCleaner.url_whitelist.include?(ENV['DATABASE_URL'])
33
+ end
34
+
35
+ def skip?
36
+ !DatabaseCleaner.url_whitelist
37
+ end
38
+ end
39
+
40
+
41
+ class RemoteDatabaseUrl
42
+ LOCAL = %w(localhost 127.0.0.1)
43
+
44
+ def run
45
+ raise Error::RemoteDatabaseUrl if !skip? && given?
46
+ end
47
+
48
+ private
49
+
50
+ def given?
51
+ remote?(ENV['DATABASE_URL'])
52
+ end
53
+
54
+ def remote?(url)
55
+ return false unless url
56
+
57
+ parsed = URI.parse(url)
58
+ return false if parsed.scheme == 'sqlite3:'
59
+
60
+ host = parsed.host
61
+ return false unless host
62
+ return false if LOCAL.include?(host)
63
+ return false if host.end_with? '.local'
64
+ true
65
+ end
66
+
67
+ def skip?
68
+ ENV['DATABASE_CLEANER_ALLOW_REMOTE_DATABASE_URL'] ||
69
+ DatabaseCleaner.allow_remote_database_url ||
70
+ DatabaseCleaner.url_whitelist
71
+ end
72
+ end
73
+
74
+ class Production
75
+ KEYS = %w(ENV RACK_ENV RAILS_ENV)
76
+
77
+ def run
78
+ raise Error::ProductionEnv.new(key) if !skip? && given?
79
+ end
80
+
81
+ private
82
+
83
+ def given?
84
+ !!key
85
+ end
86
+
87
+ def key
88
+ @key ||= KEYS.detect { |key| ENV[key] == 'production' }
89
+ end
90
+
91
+ def skip?
92
+ ENV['DATABASE_CLEANER_ALLOW_PRODUCTION'] ||
93
+ DatabaseCleaner.allow_production
94
+ end
95
+ end
96
+
97
+ CHECKS = [
98
+ RemoteDatabaseUrl,
99
+ Production,
100
+ WhitelistedUrl
101
+ ]
102
+
103
+ def run
104
+ CHECKS.each { |const| const.new.run }
105
+ end
106
+ end
107
+ end