database_cleaner 1.6.2 → 1.8.5

Sign up to get free protection for your applications and to get access to all the features.
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
data/README.markdown CHANGED
@@ -1,149 +1,76 @@
1
+ <!--
2
+ **If you're viewing this at https://github.com/DatabaseCleaner/database_cleaner,
3
+ you're reading the documentation for the `master` branch.
4
+ [View documentation for the latest release
5
+ (1.7.0).](https://github.com/DatabaseCleaner/database_cleaner/blob/v1.7.0/README.markdown)**
6
+ -->
1
7
  # Database Cleaner
2
8
 
3
9
  [![Build Status](https://travis-ci.org/DatabaseCleaner/database_cleaner.svg?branch=master)](https://travis-ci.org/DatabaseCleaner/database_cleaner)
4
10
  [![Code Climate](https://codeclimate.com/github/DatabaseCleaner/database_cleaner/badges/gpa.svg)](https://codeclimate.com/github/DatabaseCleaner/database_cleaner)
11
+ ![Gem Version](https://badge.fury.io/rb/database_cleaner.svg)
12
+ [![SemVer](https://api.dependabot.com/badges/compatibility_score?dependency-name=database_cleaner&package-manager=bundler&version-scheme=semver)](https://dependabot.com/compatibility-score.html?dependency-name=database_cleaner&package-manager=bundler&version-scheme=semver)
5
13
 
6
- Database Cleaner is a set of strategies for cleaning your database in Ruby.
14
+ Database Cleaner is a set of gems containing strategies for cleaning your database in Ruby.
7
15
 
8
16
  The original use case was to ensure a clean state during tests.
9
17
  Each strategy is a small amount of code but is code that is usually needed in any ruby app that is testing with a database.
10
18
 
11
19
  ## Gem Setup
12
20
 
21
+ Instead of using the `database_cleaner` gem directly, each ORM has its own gem. Most projects will only need the `database_cleaner-active_record` gem:
22
+
13
23
  ```ruby
14
24
  # Gemfile
15
25
  group :test do
16
- gem 'database_cleaner'
26
+ gem 'database_cleaner-active_record'
17
27
  end
18
28
  ```
19
29
 
20
- ## Supported Databases, Libraries and Strategies
21
-
22
- ActiveRecord, DataMapper, Sequel, MongoMapper, Mongoid, CouchPotato, Ohm and Redis are supported.
23
-
24
- Here is an overview of the strategies supported for each library:
25
-
26
- <table>
27
- <tbody>
28
- <tr>
29
- <th>ORM</th>
30
- <th>Truncation</th>
31
- <th>Transaction</th>
32
- <th>Deletion</th>
33
- </tr>
34
- <tr>
35
- <td> ActiveRecord </td>
36
- <td> Yes</td>
37
- <td> <b>Yes</b></td>
38
- <td> Yes</td>
39
- </tr>
40
- <tr>
41
- <td> DataMapper</td>
42
- <td> Yes</td>
43
- <td> <b>Yes</b></td>
44
- <td> No</td>
45
- </tr>
46
- <tr>
47
- <td> CouchPotato</td>
48
- <td> <b>Yes</b></td>
49
- <td> No</td>
50
- <td> No</td>
51
- </tr>
52
- <tr>
53
- <td> MongoMapper</td>
54
- <td> <b>Yes</b></td>
55
- <td> No</td>
56
- <td> No</td>
57
- </tr>
58
- <tr>
59
- <td> Mongoid</td>
60
- <td> <b>Yes</b></td>
61
- <td> No</td>
62
- <td> No</td>
63
- </tr>
64
- <tr>
65
- <td> Sequel</td>
66
- <td> <b>Yes</b></td>
67
- <td> Yes</td>
68
- <td> Yes</td>
69
- </tr>
70
- <tr>
71
- <td>Redis</td>
72
- <td><b>Yes</b></td>
73
- <td>No</td>
74
- <td>No</td>
75
- </tr>
76
- <tr>
77
- <td>Ohm</td>
78
- <td><b>Yes</b></td>
79
- <td>No</td>
80
- <td>No</td>
81
- </tr>
82
- <tr>
83
- <td>Neo4j</td>
84
- <td>Yes</td>
85
- <td>Yes*</td>
86
- <td>Yes*</td>
87
- </tr>
88
- </tbody>
89
- </table>
90
-
91
- \* Truncation and Deletion strategies for Neo4j will just delete all nodes and relationships from the database.
92
-
93
- <table>
94
- <tbody>
95
- <tr>
96
- <th>Driver</th>
97
- <th>Truncation</th>
98
- <th>Transaction</th>
99
- <th>Deletion</th>
100
- </tr>
101
- <tr>
102
- <td> Mongo</td>
103
- <td> Yes</td>
104
- <td> No</td>
105
- <td> No</td>
106
- </tr>
107
- <tr>
108
- <td> Moped</td>
109
- <td> Yes</td>
110
- <td> No</td>
111
- <td> No</td>
112
- </tr>
113
- </tbody>
114
- </table>
115
-
116
- (Default strategy for each library is denoted in bold)
30
+ If you are using multiple ORMs, just load multiple gems:
117
31
 
118
- Database Cleaner also includes a `null` strategy (that does no cleaning at all) which can be used with any ORM library.
119
- You can also explicitly use it by setting your strategy to `nil`.
120
32
 
121
- For support or to discuss development please use the [Google Group](http://groups.google.com/group/database_cleaner).
33
+ ```ruby
34
+ # Gemfile
35
+ group :test do
36
+ gem 'database_cleaner-active_record'
37
+ gem 'database_cleaner-redis'
38
+ end
39
+ ```
122
40
 
123
- ## What strategy is fastest?
41
+ ## List of adapters
124
42
 
125
- For the SQL libraries the fastest option will be to use `:transaction` as transactions are simply rolled back. If you can use this strategy you should. However, if you wind up needing to use multiple database connections in your tests (i.e. your tests run in a different process than your application) then using this strategy becomes a bit more difficult. You can get around the problem a number of ways.
43
+ Here is an overview of the databases and ORMs supported by each adapter:
126
44
 
127
- One common approach is to force all processes to use the same database connection ([common ActiveRecord hack](http://blog.plataformatec.com.br/2011/12/three-tips-to-improve-the-performance-of-your-test-suite/)) however this approach has been reported to result in non-deterministic failures.
45
+ MySQL, PostgreSQL, SQLite, etc
46
+ * [database_cleaner-active_record](adapters/database_cleaner-active_record)
47
+ * [database_cleaner-sequel](adapters/database_cleaner-sequel)
48
+ * [database_cleaner-data_mapper](adapters/database_cleaner-data_mapper)
128
49
 
129
- Another approach is to have the transactions rolled back in the application's process and relax the isolation level of the database (so the tests can read the uncommitted transactions).
50
+ CouchDB
51
+ * [database_cleaner-couch_potato](adapters/database_cleaner-couch_potato)
130
52
 
131
- An easier, but slower, solution is to use the `:truncation` or `:deletion` strategy.
53
+ MongoDB
54
+ * [database_cleaner-mongoid](adapters/database_cleaner-mongoid)
55
+ * [database_cleaner-mongo_mapper](adapters/database_cleaner-mongo_mapper)
56
+ * [database_cleaner-moped](adapters/database_cleaner-moped)
57
+ * [database_cleaner-mongo](adapters/database_cleaner-mongo)
132
58
 
133
- So what is fastest out of `:deletion` and `:truncation`? Well, it depends on your table structure and what percentage of tables you populate in an average test. The reasoning is out of the scope of this README but here is a [good SO answer on this topic for Postgres](http://stackoverflow.com/questions/11419536/postgresql-truncation-speed/11423886#11423886).
59
+ Redis
60
+ * [database_cleaner-redis](adapters/database_cleaner-redis)
61
+ * [database_cleaner-ohm](adapters/database_cleaner-ohm)
134
62
 
135
- Some people report much faster speeds with `:deletion` while others say `:truncation` is faster for them. The best approach therefore is it try all options on your test suite and see what is faster.
136
-
137
- If you are using ActiveRecord then take a look at the [additional options](#additional-activerecord-options-for-truncation) available for `:truncation`.
63
+ Neo4j
64
+ * [database_cleaner-neo4j](adapters/database_cleaner-neo4j)
138
65
 
139
- ## Dependencies
66
+ More details on available configuration options can be found in the README for the specific adapter gem that you're using.
140
67
 
141
- Because database_cleaner supports multiple ORMs, it doesn't make sense to include all the dependencies for each one in the gemspec. However, the DataMapper adapter does depend on dm-transactions. Therefore, if you use DataMapper, you must include dm-transactions in your Gemfile/bundle/gemset manually.
68
+ For support or to discuss development please use the [Google Group](https://groups.google.com/group/database_cleaner).
142
69
 
143
70
  ## How to use
144
71
 
145
72
  ```ruby
146
- require 'database_cleaner'
73
+ require 'database_cleaner/active_record'
147
74
 
148
75
  DatabaseCleaner.strategy = :truncation
149
76
 
@@ -161,15 +88,12 @@ DatabaseCleaner.strategy = :truncation, {:only => %w[widgets dogs some_other_tab
161
88
  DatabaseCleaner.strategy = :truncation, {:except => %w[widgets]}
162
89
  ```
163
90
 
164
- With Ohm and Redis, `:only` and `:except` take a list of strings to be
165
- passed to [`keys`](http://redis.io/commands/keys)).
166
-
167
91
  (I should point out the truncation strategy will never truncate your schema_migrations table.)
168
92
 
169
93
  Some strategies need to be started before tests are run (for example the `:transaction` strategy needs to know to open up a transaction). This can be accomplished by calling `DatabaseCleaner.start` at the beginning of the run, or by running the tests inside a block to `DatabaseCleaner.cleaning`. So you would have:
170
94
 
171
95
  ```ruby
172
- require 'database_cleaner'
96
+ require 'database_cleaner/active_record'
173
97
 
174
98
  DatabaseCleaner.strategy = :transaction
175
99
 
@@ -191,7 +115,7 @@ At times you may want to do a single clean with one strategy.
191
115
  For example, you may want to start the process by truncating all the tables, but then use the faster transaction strategy the remaining time. To accomplish this you can say:
192
116
 
193
117
  ```ruby
194
- require 'database_cleaner'
118
+ require 'database_cleaner/active_record'
195
119
 
196
120
  DatabaseCleaner.clean_with :truncation
197
121
 
@@ -200,17 +124,26 @@ DatabaseCleaner.strategy = :transaction
200
124
  # then make the DatabaseCleaner.start and DatabaseCleaner.clean calls appropriately
201
125
  ```
202
126
 
203
- ### Additional ActiveRecord options for Truncation
127
+ ## What strategy is fastest?
204
128
 
205
- The following options are available for ActiveRecord's `:truncation` strategy _only_ for MySQL and Postgres.
129
+ For the SQL libraries the fastest option will be to use `:transaction` as transactions are simply rolled back. If you can use this strategy you should. However, if you wind up needing to use multiple database connections in your tests (i.e. your tests run in a different process than your application) then using this strategy becomes a bit more difficult. You can get around the problem a number of ways.
206
130
 
207
- * `:pre_count` - When set to `true` this will check each table for existing rows before truncating it. This can speed up test suites when many of the tables to be truncated are never populated. Defaults to `:false`. (Also, see the section on [What strategy is fastest?](#what-strategy-is-fastest))
208
- * `:reset_ids` - This only matters when `:pre_count` is used, and it will make sure that a tables auto-incrementing id is reset even if there are no rows in the table (e.g. records were created in the test but also removed before DatabaseCleaner gets to it). Defaults to `true`.
131
+ One common approach is to force all processes to use the same database connection ([common ActiveRecord hack](http://blog.plataformatec.com.br/2011/12/three-tips-to-improve-the-performance-of-your-test-suite/)) however this approach has been reported to result in non-deterministic failures.
209
132
 
210
- The following option is available for ActiveRecord's `:truncation` and `:deletion` strategy for any DB.
133
+ Another approach is to have the transactions rolled back in the application's process and relax the isolation level of the database (so the tests can read the uncommitted transactions).
211
134
 
212
- * `:cache_tables` - When set to `true` the list of tables to truncate or delete from will only be read from the DB once, otherwise it will be read before each cleanup run. Set this to `false` if (1) you create and drop tables in your tests, or (2) you change Postgres schemas (`ActiveRecord::Base.connection.schema_search_path`) in your tests (for example, in a multitenancy setup with each tenant in a different Postgres schema). Defaults to `true`.
135
+ An easier, but slower, solution is to use the `:truncation` or `:deletion` strategy.
136
+
137
+ So what is fastest out of `:deletion` and `:truncation`? Well, it depends on your table structure and what percentage of tables you populate in an average test. The reasoning is out of the scope of this README but here is a [good SO answer on this topic for Postgres](https://stackoverflow.com/questions/11419536/postgresql-truncation-speed/11423886#11423886).
138
+
139
+ Some people report much faster speeds with `:deletion` while others say `:truncation` is faster for them. The best approach therefore is it try all options on your test suite and see what is faster.
140
+
141
+ If you are using ActiveRecord then take a look at the [additional options](#additional-activerecord-options-for-truncation) available for `:truncation`.
213
142
 
143
+ Database Cleaner also includes a `null` strategy (that does no cleaning at all) which can be used with any ORM library.
144
+ You can also explicitly use it by setting your strategy to `nil`.
145
+
146
+ ## Test Framework Examples
214
147
 
215
148
  ### RSpec Example
216
149
 
@@ -295,7 +228,7 @@ RSpec.configure do |config|
295
228
  # with the specs, so continue to use transaction strategy for speed.
296
229
  driver_shares_db_connection_with_specs = Capybara.current_driver == :rack_test
297
230
 
298
- if !driver_shares_db_connection_with_specs
231
+ unless driver_shares_db_connection_with_specs
299
232
  # Driver is probably for an external browser with an app
300
233
  # under test that does *not* share a database connection with the
301
234
  # specs, so use truncation strategy.
@@ -345,14 +278,9 @@ If you're using Cucumber with Rails, just use the generator that ships with cucu
345
278
  Otherwise, to add DatabaseCleaner to your project by hand, create a file `features/support/database_cleaner.rb` that looks like this:
346
279
 
347
280
  ```ruby
348
- begin
349
- require 'database_cleaner'
350
- require 'database_cleaner/cucumber'
281
+ require 'database_cleaner/active_record'
351
282
 
352
- DatabaseCleaner.strategy = :truncation
353
- rescue NameError
354
- raise "You need to add database_cleaner to your Gemfile (in the :test group) if you wish to use it."
355
- end
283
+ DatabaseCleaner.strategy = :truncation
356
284
 
357
285
  Around do |scenario, block|
358
286
  DatabaseCleaner.cleaning(&block)
@@ -370,11 +298,14 @@ Sometimes you need to use multiple ORMs in your application.
370
298
  You can use DatabaseCleaner to clean multiple ORMs, and multiple connections for those ORMs.
371
299
 
372
300
  ```ruby
373
- #How to specify particular orms
301
+ require 'database_cleaner/active_record'
302
+ require 'database_cleaner/mongo_mapper'
303
+
304
+ # How to specify particular orms
374
305
  DatabaseCleaner[:active_record].strategy = :transaction
375
306
  DatabaseCleaner[:mongo_mapper].strategy = :truncation
376
307
 
377
- #How to specify particular connections
308
+ # How to specify particular connections
378
309
  DatabaseCleaner[:active_record, { :connection => :two }]
379
310
 
380
311
  # You may also pass in the model directly:
@@ -383,68 +314,6 @@ DatabaseCleaner[:active_record, { :model => ModelWithDifferentConnection }]
383
314
 
384
315
  Usage beyond that remains the same with `DatabaseCleaner.start` calling any setup on the different configured connections, and `DatabaseCleaner.clean` executing afterwards.
385
316
 
386
- ### Configuration options
387
-
388
- <table>
389
- <tbody>
390
- <tr>
391
- <th>ORM</th>
392
- <th>How to access</th>
393
- <th>Notes</th>
394
- </tr>
395
- <tr>
396
- <td> Active Record </td>
397
- <td> <code>DatabaseCleaner[:active_record]</code></td>
398
- <td> Connection specified as <code>:symbol</code> keys, loaded from <code>config/database.yml</code>. You may also pass in the ActiveRecord model under the <code>:model</code> key.</td>
399
- </tr>
400
- <tr>
401
- <td> Data Mapper</td>
402
- <td> <code>DatabaseCleaner[:data_mapper]</code></td>
403
- <td> Connection specified as <code>:symbol</code> keys, loaded via Datamapper repositories </td>
404
- </tr>
405
- <tr>
406
- <td> Mongo Mapper</td>
407
- <td> <code>DatabaseCleaner[:mongo_mapper]</code></td>
408
- <td> Multiple connections not yet supported</td>
409
- </tr>
410
- <tr>
411
- <td> Mongoid</td>
412
- <td> <code>DatabaseCleaner[:mongoid]</code></td>
413
- <td> Multiple databases supported for Mongoid 3. Specify <code>DatabaseCleaner[:mongoid, {:connection =&gt; :db_name}]</code> </td>
414
- </tr>
415
- <tr>
416
- <td> Moped</td>
417
- <td> <code>DatabaseCleaner[:moped]</code></td>
418
- <td> It is necessary to configure database name with <code>DatabaseCleaner[:moped].db = db_name</code> otherwise name `default` will be used.</td>
419
- </tr>
420
- <tr>
421
- <td> Couch Potato</td>
422
- <td> <code>DatabaseCleaner[:couch_potato]</code></td>
423
- <td> Multiple connections not yet supported</td>
424
- </tr>
425
- <tr>
426
- <td> Sequel</td>
427
- <td> <code>DatabaseCleaner[:sequel]</code></td>
428
- <td> Multiple databases supported; specify <code>DatabaseCleaner[:sequel, {:connection =&gt; Sequel.connect(uri)}]</code></td>
429
- </tr>
430
- <tr>
431
- <td>Redis</td>
432
- <td><code>DatabaseCleaner[:redis]</code></td>
433
- <td>Connection specified as Redis URI</td>
434
- </tr>
435
- <tr>
436
- <td>Ohm</td>
437
- <td><code>DatabaseCleaner[:ohm]</code></td>
438
- <td>Connection specified as Redis URI</td>
439
- </tr>
440
- <tr>
441
- <td>Neo4j</td>
442
- <td><code>DatabaseCleaner[:neo4j]</code></td>
443
- <td>Database type and path(URI) <code>DatabaseCleaner[:neo4j, connection: {type: :server_db, path: 'http://localhost:7475'}].</code></td>
444
- </tr>
445
- </tbody>
446
- </table>
447
-
448
317
  ## Why?
449
318
 
450
319
  One of my motivations for writing this library was to have an easy way to turn on what Rails calls "transactional_fixtures" in my non-rails ActiveRecord projects.
@@ -455,15 +324,15 @@ After copying and pasting code to do this several times I decided to package it
455
324
 
456
325
  #### DatabaseCleaner is trying to use the wrong ORM
457
326
 
458
- DatabaseCleaner has an autodetect mechanism where if you do not explicitly define your ORM it will use the first ORM it can detect that is loaded.
327
+ DatabaseCleaner has a deprecated autodetect mechanism where if you do not explicitly define your ORM it will use the first ORM it can detect that is loaded.
459
328
 
460
329
  Since ActiveRecord is the most common ORM used that is the first one checked for.
461
330
 
462
- Sometimes other libraries (e.g. ActiveAdmin) will load other ORMs (e.g. ActiveRecord) even though you are using a different ORM. This will result in DatabaseCleaner trying to use the wrong ORM (e.g. ActiveRecord) unless you explicitly define your ORM like so:
331
+ Sometimes other libraries (e.g. ActiveAdmin) will load other ORMs (e.g. ActiveRecord) even though you are using a different ORM. This will result in DatabaseCleaner trying to use the wrong ORM (e.g. ActiveRecord) unless you explicitly require the correct adapter gem:
463
332
 
464
333
  ```ruby
465
- # How to setup your ORM explicitly
466
- DatabaseCleaner[:mongoid].strategy = :truncation
334
+ # Gemfile
335
+ gem "database_cleaner-mongoid"
467
336
  ```
468
337
 
469
338
  ### STDERR is being flooded when using Postgres
@@ -485,34 +354,36 @@ test:
485
354
  min_messages: WARNING
486
355
  </pre>
487
356
 
488
- ### Nothing happens in JRuby with Sequel using transactions
357
+ ## Safeguards
489
358
 
490
- Due to an inconsistency in JRuby's implementation of Fibers, Sequel gives a different connection to `DatabaseCleaner.start` than is used for tests run between `.start` and `.clean`. This can be worked around by running your tests in a block like `DatabaseCleaner.cleaning { run_my_tests }` instead, which does not use Fibers.
359
+ DatabaseCleaner comes with safeguards against:
491
360
 
492
- ### Model fails to load with Neo4j using transactions
361
+ * Running in production (checking for `ENV`, `RACK_ENV`, and `RAILS_ENV`)
362
+ * Running against a remote database (checking for a `DATABASE_URL` that does not include `localhost`, `.local` or `127.0.0.1`)
493
363
 
494
- When you are using [neo4j](https://github.com/neo4jrb/neo4j) gem it creates schema and reads indexes upon loading models. These operations can't be done during a transaction. You have to preload your models before DatabaseCleaner starts a transaction.
364
+ Both safeguards can be disabled separately as follows.
495
365
 
496
- Add to your rails_helper or spec_helper after requiring database_cleaner:
366
+ Using environment variables:
497
367
 
498
- ```ruby
499
- require 'database_cleaner'
500
- Dir["#{Rails.root}/app/models/**/*.rb"].each do |model|
501
- load model
502
- end
368
+ ```
369
+ export DATABASE_CLEANER_ALLOW_PRODUCTION=true
370
+ export DATABASE_CLEANER_ALLOW_REMOTE_DATABASE_URL=true
503
371
  ```
504
372
 
505
- ## Debugging
373
+ In Ruby:
506
374
 
507
- In rare cases DatabaseCleaner will encounter errors that it will log. By default it uses STDOUT set to the ERROR level but you can configure this to use whatever Logger you desire.
375
+ ```ruby
376
+ DatabaseCleaner.allow_production = true
377
+ DatabaseCleaner.allow_remote_database_url = true
378
+ ```
508
379
 
509
- Here's an example of using the `Rails.logger` in `env.rb`:
380
+ In Ruby, a URL whitelist can be specified. When specified, DatabaseCleaner will only allow `DATABASE_URL` to be equal
381
+ to one of the values specified in the url whitelist like so:
510
382
 
511
383
  ```ruby
512
- DatabaseCleaner.logger = Rails.logger
384
+ DatabaseCleaner.url_whitelist = ['postgres://postgres@localhost', 'postgres://foo@bar']
513
385
  ```
514
386
 
515
-
516
387
  ## COPYRIGHT
517
388
 
518
- Copyright (c) 2014 Ben Mabey. See LICENSE for details.
389
+ See [LICENSE](LICENSE) for details.
data/Rakefile CHANGED
@@ -1,12 +1,12 @@
1
1
  require "rubygems"
2
2
  require "bundler"
3
+ require "bundler/gem_tasks"
3
4
  Bundler.setup
4
5
 
5
6
  require 'rake'
6
7
  require 'rspec/core'
7
8
  require 'rspec/core/rake_task'
8
9
  RSpec::Core::RakeTask.new(:spec) do |spec|
9
-
10
10
  spec.pattern = FileList['spec/**/*_spec.rb']
11
11
  end
12
12
 
@@ -15,15 +15,19 @@ RSpec::Core::RakeTask.new(:rcov) do |spec|
15
15
  spec.rcov = true
16
16
  end
17
17
 
18
- begin
19
- require 'cucumber/rake/task'
20
- Cucumber::Rake::Task.new(:features)
21
- rescue LoadError
22
- puts "Cucumber is not available. In order to run features, you must: sudo gem install cucumber"
23
- end
18
+ require 'cucumber/rake/task'
19
+ Cucumber::Rake::Task.new(:features)
24
20
 
25
- task :default => [:spec, :features]
21
+ desc "Run adapter test suites"
22
+ task :adapters do
23
+ Dir["adapters/*"].each do |adapter_dir|
24
+ Dir.chdir adapter_dir do
25
+ sh "bundle exec rake"
26
+ end
27
+ end
28
+ end
26
29
 
30
+ task :default => [:spec, :features, :adapters]
27
31
 
28
32
  desc "Cleans the project of any tmp file that should not be included in the gemspec."
29
33
  task :clean do
@@ -1,20 +1,29 @@
1
- require 'database_cleaner/generic/base'
2
1
  require 'active_record'
2
+ require 'database_cleaner/generic/base'
3
3
  require 'erb'
4
+ require 'yaml'
4
5
 
5
6
  module DatabaseCleaner
6
7
  module ActiveRecord
7
-
8
8
  def self.available_strategies
9
9
  %w[truncation transaction deletion]
10
10
  end
11
11
 
12
+ def self.default_strategy
13
+ :transaction
14
+ end
15
+
12
16
  def self.config_file_location=(path)
13
17
  @config_file_location = path
14
18
  end
15
19
 
16
20
  def self.config_file_location
17
- @config_file_location ||= "#{DatabaseCleaner.app_root}/config/database.yml"
21
+ @config_file_location ||= begin
22
+ # Has DC.app_root been set? Check in this intrusive way to avoid triggering deprecation warnings if it hasn't.
23
+ app_root = DatabaseCleaner.send(:configuration).instance_variable_get(:@app_root)
24
+ root = app_root || Dir.pwd
25
+ "#{root}/config/database.yml"
26
+ end
18
27
  end
19
28
 
20
29
  module Base
@@ -79,14 +88,14 @@ module DatabaseCleaner
79
88
  if ::ActiveRecord::Base.respond_to?(:descendants)
80
89
  database_name = connection_hash["database"] || connection_hash[:database]
81
90
  models = ::ActiveRecord::Base.descendants
82
- models.detect { |m| m.connection_pool.spec.config[:database] == database_name }
91
+ models.select(&:connection_pool).detect { |m| m.connection_pool.spec.config[:database] == database_name }
83
92
  end
84
93
  end
85
94
 
86
95
  def establish_connection
87
96
  ::ActiveRecord::Base.establish_connection(connection_hash)
97
+ ::ActiveRecord::Base
88
98
  end
89
-
90
99
  end
91
100
  end
92
101
  end
@@ -1,7 +1,6 @@
1
- require 'active_record/base'
1
+ require 'active_record'
2
2
  require 'active_record/connection_adapters/abstract_adapter'
3
3
  require "database_cleaner/generic/truncation"
4
- require 'database_cleaner/active_record/base'
5
4
  require 'database_cleaner/active_record/truncation'
6
5
 
7
6
  module DatabaseCleaner
@@ -53,28 +52,31 @@ module DatabaseCleaner::ActiveRecord
53
52
  end
54
53
 
55
54
  def tables_with_new_rows(connection)
56
- @db_name ||= connection.instance_variable_get('@config')[:database]
57
- stats = table_stats_query(connection, @db_name)
55
+ stats = table_stats_query(connection)
58
56
  if stats != ''
59
- connection.exec_query(stats).inject([]) {|all, stat| all << stat['table_name'] if stat['exact_row_count'] > 0; all }
57
+ connection.select_values(stats)
60
58
  else
61
59
  []
62
60
  end
63
61
  end
64
62
 
65
- def table_stats_query(connection, db_name)
66
- if @cache_tables && !@table_stats_query.nil?
67
- return @table_stats_query
68
- else
69
- @table_stats_query = connection.select_values(<<-SQL).join(' UNION ')
70
- SELECT CONCAT('SELECT \"', table_name, '\" AS table_name, COUNT(*) AS exact_row_count FROM ', table_name)
71
- FROM
72
- INFORMATION_SCHEMA.TABLES
73
- WHERE
74
- table_schema = '#{db_name}'
75
- AND #{::DatabaseCleaner::ActiveRecord::Base.exclusion_condition('table_name')};
76
- SQL
63
+ def table_stats_query(connection)
64
+ @table_stats_query ||= build_table_stats_query(connection)
65
+ ensure
66
+ @table_stats_query = nil unless @cache_tables
67
+ end
68
+
69
+ def build_table_stats_query(connection)
70
+ tables = connection.select_values(<<-SQL)
71
+ SELECT table_name
72
+ FROM information_schema.tables
73
+ WHERE table_schema = database()
74
+ AND #{::DatabaseCleaner::ActiveRecord::Base.exclusion_condition('table_name')};
75
+ SQL
76
+ queries = tables.map do |table|
77
+ "(SELECT #{connection.quote(table)} FROM #{connection.quote_table_name(table)} LIMIT 1)"
77
78
  end
79
+ queries.join(' UNION ALL ')
78
80
  end
79
81
 
80
82
  def information_schema_exists? connection
@@ -1,10 +1,10 @@
1
1
  require 'active_record/base'
2
-
2
+ require 'database_cleaner/active_record/base'
3
3
  require 'active_record/connection_adapters/abstract_adapter'
4
4
 
5
5
  #Load available connection adapters
6
6
  %w(
7
- abstract_mysql_adapter postgresql_adapter sqlite3_adapter mysql_adapter mysql2_adapter
7
+ abstract_mysql_adapter postgresql_adapter sqlite3_adapter mysql_adapter mysql2_adapter oracle_enhanced_adapter
8
8
  ).each do |known_adapter|
9
9
  begin
10
10
  require "active_record/connection_adapters/#{known_adapter}"
@@ -27,7 +27,11 @@ module DatabaseCleaner
27
27
 
28
28
  def database_cleaner_table_cache
29
29
  # the adapters don't do caching (#130) but we make the assumption that the list stays the same in tests
30
- @database_cleaner_tables ||= ::ActiveRecord::VERSION::MAJOR >= 5 ? data_sources : tables
30
+ @database_cleaner_tables ||= database_tables
31
+ end
32
+
33
+ def database_tables
34
+ ::ActiveRecord::VERSION::MAJOR >= 5 ? data_sources : tables
31
35
  end
32
36
 
33
37
  def truncate_table(table_name)
@@ -63,22 +67,21 @@ module DatabaseCleaner
63
67
  select_value("SELECT EXISTS (SELECT 1 FROM #{quote_table_name(table)} LIMIT 1)").to_i
64
68
  end
65
69
 
66
- # Returns a boolean indicating if the given table has an auto-inc number higher than 0.
67
- # Note, this is different than an empty table since an table may populated, the index increased,
68
- # but then the table is cleaned. In other words, this function tells us if the given table
69
- # was ever inserted into.
70
- def has_been_used?(table)
71
- if has_rows?(table)
72
- true
73
- else
74
- # Patch for MysqlAdapter with ActiveRecord 3.2.7 later
75
- # select_value("SELECT 1") #=> "1"
76
- select_value(<<-SQL).to_i > 1 # returns nil if not present
77
- SELECT Auto_increment
70
+ def auto_increment_value(table)
71
+ select_value(<<-SQL).to_i
72
+ SELECT auto_increment
78
73
  FROM information_schema.tables
79
- WHERE table_name='#{table}';
80
- SQL
81
- end
74
+ WHERE table_name = '#{table}'
75
+ AND table_schema = database()
76
+ SQL
77
+ end
78
+
79
+ # This method tells us if the given table has been inserted into since its
80
+ # last truncation. Note that the table might have been populated, which
81
+ # increased the auto-increment counter, but then cleaned again such that
82
+ # it appears empty now.
83
+ def has_been_used?(table)
84
+ has_rows?(table) || auto_increment_value(table) > 1
82
85
  end
83
86
 
84
87
  def has_rows?(table)
@@ -244,7 +247,7 @@ module DatabaseCleaner::ActiveRecord
244
247
  private
245
248
 
246
249
  def tables_to_truncate(connection)
247
- tables_in_db = cache_tables? ? connection.database_cleaner_table_cache : connection.tables
250
+ tables_in_db = cache_tables? ? connection.database_cleaner_table_cache : connection.database_tables
248
251
  to_reject = (@tables_to_exclude + connection.database_cleaner_view_cache)
249
252
  (@only || tables_in_db).reject do |table|
250
253
  if ( m = table.match(/([^.]+)$/) )
@@ -257,7 +260,9 @@ module DatabaseCleaner::ActiveRecord
257
260
 
258
261
  # overwritten
259
262
  def migration_storage_names
260
- [::DatabaseCleaner::ActiveRecord::Base.migration_table_name]
263
+ result = [::DatabaseCleaner::ActiveRecord::Base.migration_table_name]
264
+ result << ::ActiveRecord::Base.internal_metadata_table_name if ::ActiveRecord::VERSION::MAJOR >= 5
265
+ result
261
266
  end
262
267
 
263
268
  def cache_tables?