pax_global_header00006660000000000000000000000064132661753070014524gustar00rootroot0000000000000052 comment=0dcf095f71db55f4c6e4c1d3a93869df91aa2e13 database_cleaner-1.7.0/000077500000000000000000000000001326617530700147665ustar00rootroot00000000000000database_cleaner-1.7.0/.gitignore000066400000000000000000000002641326617530700167600ustar00rootroot00000000000000*.sw? .DS_Store coverage pkg .bundle bundled_gems/ vendor/ examples/db/*.db examples/config/database.yml db/config.yml db/test.sqlite3 .rbenv-version .rvmrc .ruby-version .vagrant database_cleaner-1.7.0/.rspec000066400000000000000000000000611326617530700161000ustar00rootroot00000000000000--color --format documentation mtime --backtrace database_cleaner-1.7.0/.ruby-version.sample000066400000000000000000000000111326617530700207030ustar00rootroot000000000000002.1.2@db database_cleaner-1.7.0/.travis.yml000066400000000000000000000013041326617530700170750ustar00rootroot00000000000000language: ruby rvm: - 1.9.3 - 2.0.0 - 2.1 - 2.2 script: - bundle exec rspec # - bundle exec cucumber gemfile: - Gemfile before_install: - gem install bundler -v 1.14.6 # install Neo4j locally: - wget dist.neo4j.org/neo4j-community-2.3.3-unix.tar.gz - tar -xzf neo4j-community-2.3.3-unix.tar.gz - sed -i.bak s/dbms.security.auth_enabled=true/dbms.security.auth_enabled=false/g neo4j-community-2.3.3/conf/neo4j-server.properties - neo4j-community-2.3.3/bin/neo4j start before_script: - mysql -e 'create database database_cleaner_test;' - psql -c 'create database database_cleaner_test;' -U postgres - cp db/sample.config.yml db/config.yml services: - redis-server - mongodb database_cleaner-1.7.0/CONTRIBUTE.markdown000066400000000000000000000015371326617530700202160ustar00rootroot00000000000000# Guidelines for contributing ## 1. Fork & Clone Since you probably don't have rights to the main repo, you should Fork it (big button up top). After that, clone your fork locally and optionally add an upstream: git remote add upstream git@github.com:DatabaseCleaner/database_cleaner.git ## 2. Make sure the tests run fine - `bundle install` - Copy `db/sample.config.yml` to `db/config.yml` and edit it - Make sure to create the databases specified in `db/config.yml` - Run the tests with `bundle exec rspec` Note that if you don't have all the supported databases installed and running, some tests will fail. ## 3. Prepare your contribution This is all up to you but a few points should be kept in mind: - Please write tests for your contribution - Make sure that previous tests still pass - Push it to a branch of your fork - Submit a pull request database_cleaner-1.7.0/Gemfile000066400000000000000000000000101326617530700162500ustar00rootroot00000000000000gemspec database_cleaner-1.7.0/Gemfile.lock000066400000000000000000000143441326617530700172160ustar00rootroot00000000000000PATH remote: . specs: database_cleaner (1.6.3) GEM remote: https://rubygems.org/ specs: abstract (1.0.0) actionpack (3.0.0) activemodel (= 3.0.0) activesupport (= 3.0.0) builder (~> 2.1.2) erubis (~> 2.6.6) i18n (~> 0.4.1) rack (~> 1.2.1) rack-mount (~> 0.6.12) rack-test (~> 0.5.4) tzinfo (~> 0.3.23) activemodel (3.0.0) activesupport (= 3.0.0) builder (~> 2.1.2) i18n (~> 0.4.1) activerecord (3.0.0) activemodel (= 3.0.0) activesupport (= 3.0.0) arel (~> 1.0.0) tzinfo (~> 0.3.23) activerecord-mysql2-adapter (0.0.3) mysql2 activesupport (3.0.0) addressable (2.3.6) arel (1.0.1) activesupport (~> 3.0.0) bcrypt (3.1.7) bcrypt (3.1.7-java) bcrypt-ruby (3.1.5) bcrypt (>= 3.1.3) bcrypt-ruby (3.1.5-java) bcrypt (>= 3.1.3) bson (1.11.1) bson (1.11.1-java) bson_ext (1.11.1) bson (~> 1.11.1) builder (2.1.2) coderay (1.1.0) couch_potato (1.3.0) activemodel couchrest (~> 1.2.0) json (~> 1.6) couchrest (1.2.0) mime-types (~> 1.15) multi_json (~> 1.0) rest-client (~> 1.6.1) cucumber (1.2.1) builder (>= 2.1.2) diff-lcs (>= 1.1.3) gherkin (~> 2.11.0) json (>= 1.4.6) data_objects (0.10.14) addressable (~> 2.1) datamapper (1.2.0) dm-aggregates (~> 1.2.0) dm-constraints (~> 1.2.0) dm-core (~> 1.2.0) dm-migrations (~> 1.2.0) dm-serializer (~> 1.2.0) dm-timestamps (~> 1.2.0) dm-transactions (~> 1.2.0) dm-types (~> 1.2.0) dm-validations (~> 1.2.0) diff-lcs (1.2.5) dm-aggregates (1.2.0) dm-core (~> 1.2.0) dm-constraints (1.2.0) dm-core (~> 1.2.0) dm-core (1.2.1) addressable (~> 2.3) dm-do-adapter (1.2.0) data_objects (~> 0.10.6) dm-core (~> 1.2.0) dm-migrations (1.2.0) dm-core (~> 1.2.0) dm-serializer (1.2.2) dm-core (~> 1.2.0) fastercsv (~> 1.5) json (~> 1.6) json_pure (~> 1.6) multi_json (~> 1.0) dm-sqlite-adapter (1.2.0) dm-do-adapter (~> 1.2.0) do_sqlite3 (~> 0.10.6) dm-timestamps (1.2.0) dm-core (~> 1.2.0) dm-transactions (1.2.0) dm-core (~> 1.2.0) dm-types (1.2.2) bcrypt-ruby (~> 3.0) dm-core (~> 1.2.0) fastercsv (~> 1.5) json (~> 1.6) multi_json (~> 1.0) stringex (~> 1.4) uuidtools (~> 2.1) dm-validations (1.2.0) dm-core (~> 1.2.0) do_jdbc (0.10.14-java) data_objects (= 0.10.14) do_sqlite3 (0.10.14) data_objects (= 0.10.14) do_sqlite3 (0.10.14-java) data_objects (= 0.10.14) do_jdbc (= 0.10.14) jdbc-sqlite3 (>= 3.5.8) erubis (2.6.6) abstract (>= 1.0.0) faraday (0.9.0) multipart-post (>= 1.2, < 3) faraday_middleware (0.9.1) faraday (>= 0.7.4, < 0.10) fastercsv (1.5.5) ffi (1.9.6) ffi (1.9.6-java) formatador (0.2.5) gherkin (2.11.6) json (>= 1.7.6) gherkin (2.11.6-java) json (>= 1.7.6) guard (1.8.3) formatador (>= 0.2.4) listen (~> 1.3) lumberjack (>= 1.0.2) pry (>= 0.9.10) thor (>= 0.14.6) guard-rspec (2.5.4) guard (>= 1.1) rspec (~> 2.11) httparty (0.13.3) json (~> 1.8) multi_xml (>= 0.5.2) httpclient (2.5.3.3) i18n (0.4.2) jdbc-sqlite3 (3.8.10.1) json (1.8.6) json (1.8.6-java) json_pure (1.8.1) listen (1.3.1) rb-fsevent (>= 0.9.3) rb-inotify (>= 0.9) rb-kqueue (>= 0.2) lumberjack (1.0.9) method_source (0.8.2) mime-types (1.25.1) mongo (1.11.1) bson (= 1.11.1) mongo_ext (0.19.3) mongo_mapper (0.12.0) activemodel (~> 3.0) activesupport (~> 3.0) plucky (~> 0.5.2) mongoid (2.2.6) activemodel (~> 3.0.0) mongo (~> 1.3) tzinfo (~> 0.3.22) mongoid-tree (0.7.0) mongoid (~> 2.0) moped (1.5.2) multi_json (1.2.0) multi_xml (0.5.5) multipart-post (2.0.0) mysql (2.9.1) mysql2 (0.3.18) neo4j-community (2.1.5) neo4j-core (3.0.8) activesupport faraday (~> 0.9.0) faraday_middleware (~> 0.9.1) httparty httpclient json neo4j-community (~> 2.1.1) net-http-persistent os zip nest (1.1.2) redis net-http-persistent (2.9.4) ohm (0.1.5) nest (~> 1.0) os (0.9.6) pg (0.18.2) plucky (0.5.2) mongo (~> 1.5) pry (0.10.1) coderay (~> 1.1.0) method_source (~> 0.8.1) slop (~> 3.4) pry (0.10.1-java) coderay (~> 1.1.0) method_source (~> 0.8.1) slop (~> 3.4) spoon (~> 0.0) rack (1.2.8) rack-mount (0.6.14) rack (>= 1.0.0) rack-test (0.5.7) rack (>= 1.0) railties (3.0.0) actionpack (= 3.0.0) activesupport (= 3.0.0) rake (>= 0.8.4) thor (~> 0.14.0) rake (11.1.2) rb-fsevent (0.9.4) rb-inotify (0.9.5) ffi (>= 0.5.0) rb-kqueue (0.2.3) ffi (>= 0.5.0) rdoc (4.1.2) json (~> 1.4) redis (3.1.0) rest-client (1.6.8) mime-types (~> 1.16) rdoc (>= 2.4.2) rspec (2.14.1) rspec-core (~> 2.14.0) rspec-expectations (~> 2.14.0) rspec-mocks (~> 2.14.0) rspec-core (2.14.8) rspec-expectations (2.14.5) diff-lcs (>= 1.1.3, < 2.0) rspec-mocks (2.14.6) rspec-rails (2.14.2) actionpack (>= 3.0) activemodel (>= 3.0) activesupport (>= 3.0) railties (>= 3.0) rspec-core (~> 2.14.0) rspec-expectations (~> 2.14.0) rspec-mocks (~> 2.14.0) sequel (3.21.0) slop (3.6.0) spoon (0.0.4) ffi sqlite3 (1.3.10) stringex (1.5.1) thor (0.14.6) tzinfo (0.3.48) uuidtools (2.1.5) zip (2.0.2) PLATFORMS java ruby DEPENDENCIES activerecord activerecord-mysql2-adapter bson_ext bundler couch_potato cucumber database_cleaner! datamapper dm-migrations dm-sqlite-adapter guard-rspec json_pure mongo_ext mongo_mapper mongoid mongoid-tree moped mysql (~> 2.9.1) mysql2 neo4j-core ohm (~> 0.1.3) pg rake rspec-rails (~> 2.14.2) sequel (~> 3.21.0) sqlite3 tzinfo BUNDLED WITH 1.15.0 database_cleaner-1.7.0/Guardfile000066400000000000000000000003761326617530700166210ustar00rootroot00000000000000# A sample Guardfile # More info at https://github.com/guard/guard#readme guard 'rspec', :version => 2 do watch(%r{^spec/.+_spec\.rb$}) watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" } watch('spec/spec_helper.rb') { "spec" } end database_cleaner-1.7.0/History.rdoc000066400000000000000000000364751326617530700173170ustar00rootroot00000000000000== Development (master) === Bug Fixes === Changes == 1.7.0 2017-04-19 === Bug Fixes * Remove unnecessary folders from gem: https://github.com/DatabaseCleaner/database_cleaner/pull/508 * Properly quote table names: https://github.com/DatabaseCleaner/database_cleaner/pull/501 * Use more idiomatic Ruby in README: https://github.com/DatabaseCleaner/database_cleaner/pull/510 * Return ::ActiveRecord::Base from `establish_connection`: https://github.com/DatabaseCleaner/database_cleaner/pull/399 === Changes * Safeguard against running in production or running against a remote database: https://github.com/DatabaseCleaner/database_cleaner/pull/521 == 1.6.2 2017-10-29 === Bug Fixes * ActiveRecord::Base namespace patch: https://github.com/DatabaseCleaner/database_cleaner/pull/490 * Better exclusion condition based on Rails version: https://github.com/DatabaseCleaner/database_cleaner/pull/487 === Changes * Better documentation. Typos were fixed. Sequel deletion is supported: https://github.com/DatabaseCleaner/database_cleaner/pull/500 == 1.6.1 2017-05-09 === Bug Fixes * Deletion strategy fix for ActiveRecord (@kawamoto) == 1.6.0 2017-05-04 === New Features/Changes * Rails 5.1 support: Remove deprecation warning (@activefx) * MySQL 5.6+ InnoDB support (@ahorek) * Better documentation (fixed typo) (@hoshinotsuyoshi) === Bug Fixes * Fix Redis db option (@soylent) * Make NullStrategy API-complete (@anicholson) == 1.5.3 2016-04-22 === Bug Fixes * @P9GIT fixed issue #436 == 1.5.2 2016-04-17 === New Features/Changes * Use default_client with mongoid 5.0 (@stjhimy) * Added comparable support for strategies (@st0012) * Better README instructions that suggest `append_after` (@jrochkind) * Removed deprecation warnings for Rails 5.0+ (@pschambacher) * Upgrade to RSpec 2.14 (@skalee) === Bug Fixes * @dmitrypol fixed issue #409 * @schmierkov fixed the Travis builds with PR #416 * @shosti fixed issue #345 * @kylev fixed issue #379 * @skalee fixed the Travis builds for Neo4j with PR #433 == 1.5.1 2015-09-05 == Bug Fix * Added mongo2 missing files to the gemspec. (@geerzo) == 1.5.0 2015-09-02 === New Features/Changes * Use ensure within the cleaning method. (@cema-sp) * Restored mysql2 + jruby support. (@ahorek) * Added required ruby version to gemspec. (@garethrees) * Added support for Mongoid 5.0 and Mongo Ruby Driver 2.0. (@jprincipe) * Added support for additional Neo4j::Session.open options. (@brienw) * And a bunch of code style and README improvements === Bug Fixes * Fixed truncation for MongoDB 3. (@andreale) * Fixed YAML error when building gem. (@joshnesbitt) * Fixed deletion strategy for JDBC MySQL. (@DanElbert) * Fixed open transactions for multiple connections. (@claptimes5) == 1.4.1 2015-03-09 * Support for deletion with Sequel. (@cyberdelia) * Use ActiveRecord::Base configuration when different from config file. (@wendy0402) * Removed dependency of Mongo. (@codegourmet) * Fixed issue with tables schema prefix in Postgres. (@phoenixek12) * Use ruby 1.8 syntax. (@daniel-g) * Added license to gemspec. (@chrismar035) * Improved coverage for migrations table. (@jonallured) == 1.4.0 2014-12-17 === New Features/Changes * Support for Neo4j. (@dpisarewski) * Support for multiple connections on Mongoid. (@nyarly) === Better Performance * Using the deletion strategy with Mysql now only deletes those tables which have had records added to them. (@MadRabbit) * Add support for pre_count on Sequel with Mysql. (@vrinek) * Cache collection names in mongo's truncation strategy. (@nyarly) === Bug Fixes * Fix undefined method error with DataMapper SQLite adaptor. (@lanej) * Fully define Mysql2 adaptor constant. (@jgonera) * Don't truncate schema tables in Postgres. (@billywatson) * Fix issue where Moped cleaner was missing collections with 'system' in their name. (@MartinNowak) == 1.3.0 2014-05-23 === New Features/Changes * Introduced `DatabaseCleaner::cleaning` method that takes a block. (@ethco) * Improved Sequel support and added more tests (@ethco, @rhunter) === Bug Fixes * Fixed an issue with the `Transaction` strategy and Active Record where application-level transactions are not rolledback correctly. (Godfrey Chan) * activerecord-oracle_enhanced-adapter now works again (#259, @sockmonk) == 1.2.0 2013-10-09 A huge thanks goes to @tommeier for fixing the bug with class loading that was cuasing the wrong adapters to be used in certain cases. === New Features/Changes * Upgraded RSpec to remove deprecation warnings (John Rowe) * Caching of tables to truncate is now optional (@marcoow) === Bug Fixes * Use class_eval loading of superclasses to ensure right version of class is patched. (Tom Meier, Joel Nimety, Ernesto Tagwerker) * Add truncate_tables method to SQLiteAdapter. (Chris Mo) * Fixes missing #uses_sequence invokation in adapter classes for sqlite and sqlite3 (Lefteris Laskaridis) == 1.1.1 2013-08-01 === Bug Fixes * Fixes typo in Postgres superclass (POSTGRE_ADAPTER_PARENT > POSTGRES_ADAPTER_PARENT) (Joel Nimety) == 1.1.0 2013-08-01 === New Features/Changes * schema_migrations table name is now retrieved from ActiveRecord (Kyle Stevens) * Autoloading logic is now exposed, see PR #212 for details (Jeff Felchner) === Bug Fixes * Deletion strategy works again on MySQL, had to roll back multiple statements patch. * Fix MySqlAdapter superclass bug via class_eval loading of superclasses (Tom Meier) * Sequel strategy fix dealing with symbol/string mismatch on table names. (Fred Wu) == 1.0.1 2013-05-13 * Patch release to fix broken gemspec file. Sorry folks! == 1.0.0 2013-05-13 === New Features/Changes * Dropping support for Ruby 1.8.x; Only 1.9.x and beyond will be supported going forward. * Now supporting and testing against ruby 2.0.x. * Adds support for AR 4.0 by using `begin_transaction` (David Chelimsky and Steve Madsen) * Adds Rails 4 support for SQLite3Adapter * Suppport for Moped when used without Mongoid (Cyprian Kowalczyk) * Redis & Ohm support (Hengbin Qiu, James Conroy-Finn) * CI Improvements (Jan Vlnas, Murahashi Sanemat Kenichi, Samer Masry, Jordan Hollinger) * README/Documentation improvements (Marcelo Cajueiro, Donald Ball, TJ Chambers, Nick Huanca, Justin Edwards, Ryota Arai) === Bug Fixes * Fixes transaction errors when using `after_commit` hooks in AR. * Fixes truncation error with SQLite (Daniel White) * Fixes `pre_count` logic in AR Postgres. (Jordan Hollinger) * Sequel fix to normalize all table names to strings. (Lauri Peltola) * #clean_with now works with multiple connections. (John Ferlito) * Always start a AR transaction to prevent nil errors in AR when rolling back (John Hampton, M.Shibuya) == 0.9.1 2012-10-11 (0.9.0 was released first but was yanked due to bad gemspec) === New Features * New options for AR :truncation for speed. See README for details. (Stanislaw Pankevich) * view caching works with the schema_plus gem loaded * ActiveRecord::ConnectionAdapters::AbstractAdapter#views was renamed to an internal name * ActiveRecord truncation strategy caches the list of tables #130 (Petteri Räty) * Caches AR DB connections which speeds up cleaning with multiple DBs and allows for transation strategy. * MongoDB :truncation strategy (wihtout use of additional library like Mogoid). #138 (Christopher Darrell & Richard Luther/@sidereel) * Add Sequel support for multiple migration storage names in #148 (Jack Chu) * Multiple database support for Mongoid 3 #149 (Luke Francl) === Bug Fixes * :deletion for AR Postgres in JRuby now works #140 (Heiko Seebach) * Rescue LoadError when AR adapters not available. #145 (Garrow Bedrossian) * Fixes DatabaseCleaner::[] to cache cleaners. == 0.8.0 2012-06-02 * Faster truncation strategy for ActiveRecord with MySQL or PostgreSQL * Upgrade to RSpec 2 * Support for Mongoid 3/Moped (Andrew Bennett) * Postgres Adapter no longer generates invalid SQL when no tables provided. (Michael-Keith Bernard) == 0.7.2 2012-03-21 * Proper Mysql2Adapter superclass fix. (Jonathan Viney) * Sequel::Transaction works with latest Sequel. (David Barri) * Documenation fixes/improvements. (David Barri, Ben Mabey, Kevin Moore) == 0.7.1 2012-01-15 === New Features * Support for Rails 3.2. (David Demaree) === Bugfixes * Truncation resets the id count on SQLite. (Jordan Hollinger) * AR delete strategy now disables referential integrity. (Ben Mabey) * Fixes Postgres adapter for JRuby. (Dmytrii Nagirniak, Uģis Ozols) * Documenation fixes. (Josh Rendek, Joshua Flanagan) * Fixes bad error message when no database is specified for AR. (issue #72, Ben Mabey) == 0.7.0 2011-11-12 === New Features * Sequel Support (Corin Langosch) * Updates DataMapper strategies to work with DataMapper 1.1 (Xavier Shay and Anthony Williams) * for AR and PSQL, truncate all tables with one command, improving performance due to avoiding cascades (Leonid Shevtsov) === Bugfixes * Avoids trying to load the ':default' ActiveRecord config. #72 (Ben Mabey) == 0.6.7 2011-04-21 === Bugfixes * Explicity require ERB. (Vít Ondruch) * Cache DB connections, fixes referential integrity bug when using multiple DBs. (John Ferlito) == 0.6.6 2011-03-16 === Bugfixes * Don't modify the array passed in with the :except key. (Eric Wollesen) * Fixes version checking for postgresql. (Greg Barnett) == 0.6.5 2011-03-08 === Bugfixes * When truncating in postgresql (>= 8.4) sequences are now reset. (Greg Barnett) * Fixes the MongoDB truncation so non system collections starting with 'system' are not excluded for truncation. (Dmitry Naumov) == 0.6.4 2011-02-21 === Bugfixes * Avoids trying to drop views in Postgres. (Bernerd Schaefer) == 0.6.3 2011-02-09 === New Features * Configurable logger to aid in debugging database cleaner. (Marty Haught) == 0.6.2 2011-02-04 === New Features * Support IBM_DB Adapter for table truncation. This is for DB2 >= 9.7 (GH-39 Samer Abukhait) === Bugfixes * Reversed GH-41 after larger community discussion. Mongo indexes are no longer dropped. (Ben Mabey) * Truncation strategy works on SqlServer tables with FKs. (GH-33, Hugo Freire) == 0.6.1 2011-01-27 === New Features * Default strategies for all ORM libs are defined. (GH-36, GH-38 Prem Sichanugrist) * Add a NullStrategy. (GH-6 Ben Mabey) === Bugfixes * Mongo colletion indexes are dropped for collections being removed. (GH-41 Ben Mabey) * Exclude database views from tables_to_truncate, if the connection adapter supports reading from the ANSI standard information_schema views. (GH-25 Samer Abukhait) * ORM types can be specified in string format and not mysteriously blowup. (GH-26 Ben Mabey) * Do not remove MongoDB reserved system collections. (GH-24 Ches Martin) == 0.6.0 2010-10-25 - The Multi-ORM/Connection Release This release has the often asked for functionality of being able to clean multiple databases within the same project. This involves being able to clean databases managed by the same ORM (i.e. different connections) and also being able to clean databases managed by distinct ORMs. So, for example you can now use DatabaseCleaner on a project that has ActiveRecord and Mongoid to help ensure all DBs all in a clean state. Please see the README for more information. The old API has been preserved so this release is backwards compatible. This release is a result of Jon Rowe's hard work. Many thanks to Jon for all of the hours and effort he put into making this feature request a reality. === New Features * Ability to clean multiple database connections managed by the same ORM. (Jon Rowe) * Ability to clean multiple DBs managed by different ORMs in same project. (Jon Rowe) * Allows for the ActiveRecord config file (database.yml) to contain ERB and process it. (Fletcher Nichol) * Mysql2Adapter support. (Kamal Fariz Mahyuddin and John Ferlito) * Deletion strategy for ActiveRecord (Mikl Kurkov) === Bugfixes * Updates the DataMapper truncation strategy to version 0.10.3. (Robert Rouse) * Addresses Ruby 1.9 and 1.8 differences causing a bug in the AR PostgreSQLAdapter truncation strategy. (GH-14, James B. Byrne) * Fixes syntax error that MySQL was throwing during DataMapper truncation. (Blake Gentry) * Fixes truncation for PostgreSQL (Bodaniel Jeanes and Gabriel Sobrinho) * Workaround for superclass mismatches for the ActiveRecord-jdbc-adapter (Toms Mikoss) == 0.5.2 === Bugfixes * Removes extraneous puts call from configuration.rb. (Ben Mabey) == 0.5.1 - The Mongoid Release This release also attempts to fix AR for Rails 3 support. I have seen mixed reviews on this. Some people claim the fixes allow for use in Rails3 while others have not had good luck with it. I plan on reworking the way AR support is added so that it is more friendly with how Rails 3 uses autoload. === New features * Clean and clean_with methods are now aliased to clean! and clean_with!. (Ben Mabey) * Mongoid Support! (Sidney Burks) === Bugfixes * Check PostgreSQL version >= 8.2 before using TRUNCATE CASCADE (James B. Byrne) * Correct superclass is used in ActiveRecord connection adapters. (johnathan, Aslak Hellesoy, Ben Mabey) == 0.5.0 2010-02-22 - The CouchPotato Release === New features * Basic truncation support for CouchPotato / CouchDB. (Martin Rehfeld) * SQLite3 on JRuby will fall back to delete if truncate doesn't work. (Darrin Holst) * JDBC is used for ActiveRecord automaticaly when JRuby is detected. (Darrin Holst) === Bufixes * MongoMapper truncation strategy now works with :only and :except options. (Ben Mabey) == 0.4.3 2010-01-17 === New features * Truncation for ActiveRecord oracle_enhanced adapter. (Edgars Beigarts) == 0.4.2 2010-01-12 === Bufixes * Datamapper truncation now uses 'select' instead of deprecated the 'query' method. (Steve Tooke) == 0.4.1 2010-01-07 === Bufixes * Postgres tables with FKs now truncate (added TRUNCADE CASCADE) using Datamapper. (Ben Mabey) == 0.4.0 2009-12-23 (The MongoMapper Edition) === New features * MongoMapper support for the truncation strategy. (Aubrey Holland) == 0.3.0 2009-12-20 === New features * DataMapper 0.10.0 Compatible. (Martin Gamsjaeger) === Bufixes * Postgres tables with FKs now truncate (added TRUNCADE CASCADE). (Vika - yozhyk on github) == 0.2.3 2009-05-30 === New features * Support for SQL Server truncation (Adam Meehan) == 0.2.2 2009-05-08 === Bufixes * Added proper gemspec description and summary. (Ben Mabey, thanks to Martin Gamsjaeger) === New features == 0.2.1 2009-05-08 === Bufixes * Removed extraneous TruncationBase class definition. (Ben Mabey) == 0.2.0 2009-05-08 - The Datamapper Release === New features * DataMapper strategies (Martin Gamsjaeger) * Transaction * Truncation - working SQLite3, MySQL adapters. Experimental Postgres adapter (not tested). == 0.1.3 2009-04-30 === New features * PostgresSQLAdapter for AR to support the truncation strategy. (Alberto Perdomo) === Bufixes * Added missing quotes around table names in truncation calls. (Michael MacDonald) == 0.1.2 2009-03-05 === New features * JDBC Adapter to enable AR truncation strategy to work. (Kamal Fariz Mahyuddin) == 0.1.1 2009-03-04 - Initial Release (Ben Mabey) * Basic infrastructure * Features, RSpec code examples * ActiveRecord strategies * Truncation - with MySQL, and SQLite3 adapters. * Transaction - wrap your modifications and roll them back. database_cleaner-1.7.0/LICENSE000066400000000000000000000020351326617530700157730ustar00rootroot00000000000000Copyright (c) 2009 Ben Mabey Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. database_cleaner-1.7.0/README.markdown000066400000000000000000000440231326617530700174720ustar00rootroot00000000000000# Database Cleaner [![Build Status](https://travis-ci.org/DatabaseCleaner/database_cleaner.svg?branch=master)](https://travis-ci.org/DatabaseCleaner/database_cleaner) [![Code Climate](https://codeclimate.com/github/DatabaseCleaner/database_cleaner/badges/gpa.svg)](https://codeclimate.com/github/DatabaseCleaner/database_cleaner) Database Cleaner is a set of strategies for cleaning your database in Ruby. The original use case was to ensure a clean state during tests. 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. ## Gem Setup ```ruby # Gemfile group :test do gem 'database_cleaner' end ``` ## Supported Databases, Libraries and Strategies ActiveRecord, DataMapper, Sequel, MongoMapper, Mongoid, CouchPotato, Ohm and Redis are supported. Here is an overview of the strategies supported for each library:
ORM Truncation Transaction Deletion
ActiveRecord Yes Yes Yes
DataMapper Yes Yes No
CouchPotato Yes No No
MongoMapper Yes No No
Mongoid Yes No No
Sequel Yes Yes Yes
Redis Yes No No
Ohm Yes No No
Neo4j Yes Yes* Yes*
\* Truncation and Deletion strategies for Neo4j will just delete all nodes and relationships from the database.
Driver Truncation Transaction Deletion
Mongo Yes No No
Moped Yes No No
(Default strategy for each library is denoted in bold) Database Cleaner also includes a `null` strategy (that does no cleaning at all) which can be used with any ORM library. You can also explicitly use it by setting your strategy to `nil`. For support or to discuss development please use the [Google Group](http://groups.google.com/group/database_cleaner). ## What strategy is fastest? 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. 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. 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). An easier, but slower, solution is to use the `:truncation` or `:deletion` strategy. 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). 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. If you are using ActiveRecord then take a look at the [additional options](#additional-activerecord-options-for-truncation) available for `:truncation`. ## Dependencies 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. ## How to use ```ruby require 'database_cleaner' DatabaseCleaner.strategy = :truncation # then, whenever you need to clean the DB DatabaseCleaner.clean ``` With the `:truncation` strategy you can also pass in options, for example: ```ruby DatabaseCleaner.strategy = :truncation, {:only => %w[widgets dogs some_other_table]} ``` ```ruby DatabaseCleaner.strategy = :truncation, {:except => %w[widgets]} ``` With Ohm and Redis, `:only` and `:except` take a list of strings to be passed to [`keys`](http://redis.io/commands/keys)). (I should point out the truncation strategy will never truncate your schema_migrations table.) 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: ```ruby require 'database_cleaner' DatabaseCleaner.strategy = :transaction DatabaseCleaner.start # usually this is called in setup of a test dirty_the_db DatabaseCleaner.clean # cleanup of the test # OR DatabaseCleaner.cleaning do dirty_the_db end ``` At times you may want to do a single clean with one strategy. 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: ```ruby require 'database_cleaner' DatabaseCleaner.clean_with :truncation DatabaseCleaner.strategy = :transaction # then make the DatabaseCleaner.start and DatabaseCleaner.clean calls appropriately ``` ### Additional ActiveRecord options for Truncation The following options are available for ActiveRecord's `:truncation` strategy _only_ for MySQL and Postgres. * `: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)) * `: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`. The following option is available for ActiveRecord's `:truncation` and `:deletion` strategy for any DB. * `: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`. ### RSpec Example ```ruby RSpec.configure do |config| config.before(:suite) do DatabaseCleaner.strategy = :transaction DatabaseCleaner.clean_with(:truncation) end config.around(:each) do |example| DatabaseCleaner.cleaning do example.run end end end ``` ### RSpec with Capybara Example You'll typically discover a feature spec is incorrectly using transaction instead of truncation strategy when the data created in the spec is not visible in the app-under-test. A frequently occurring example of this is when, after creating a user in a spec, the spec mysteriously fails to login with the user. This happens because the user is created inside of an uncommitted transaction on one database connection, while the login attempt is made using a separate database connection. This separate database connection cannot access the uncommitted user data created over the first database connection due to transaction isolation. For feature specs using a Capybara driver for an external JavaScript-capable browser (in practice this is all drivers except `:rack_test`), the Rack app under test and the specs do not share a database connection. When a spec and app-under-test do not share a database connection, you'll likely need to use the truncation strategy instead of the transaction strategy. See the suggested config below to temporarily enable truncation strategy for affected feature specs only. This config continues to use transaction strategy for all other specs. It's also recommended to use `append_after` to ensure `DatabaseCleaner.clean` runs *after* the after-test cleanup `capybara/rspec` installs. ```ruby require 'capybara/rspec' #... RSpec.configure do |config| config.use_transactional_fixtures = false config.before(:suite) do if config.use_transactional_fixtures? raise(<<-MSG) Delete line `config.use_transactional_fixtures = true` from rails_helper.rb (or set it to false) to prevent uncommitted transactions being used in JavaScript-dependent specs. During testing, the app-under-test that the browser driver connects to uses a different database connection to the database connection used by the spec. The app's database connection would not be able to access uncommitted transaction data setup over the spec's database connection. MSG end DatabaseCleaner.clean_with(:truncation) end config.before(:each) do DatabaseCleaner.strategy = :transaction end config.before(:each, type: :feature) do # :rack_test driver's Rack app under test shares database connection # with the specs, so continue to use transaction strategy for speed. driver_shares_db_connection_with_specs = Capybara.current_driver == :rack_test unless driver_shares_db_connection_with_specs # Driver is probably for an external browser with an app # under test that does *not* share a database connection with the # specs, so use truncation strategy. DatabaseCleaner.strategy = :truncation end end config.before(:each) do DatabaseCleaner.start end config.append_after(:each) do DatabaseCleaner.clean end end ``` ### Minitest Example ```ruby DatabaseCleaner.strategy = :transaction class Minitest::Spec before :each do DatabaseCleaner.start end after :each do DatabaseCleaner.clean end end # with the minitest-around gem, this may be used instead: class Minitest::Spec around do |tests| DatabaseCleaner.cleaning(&tests) end end ``` ### Cucumber Example If you're using Cucumber with Rails, just use the generator that ships with cucumber-rails, and that will create all the code you need to integrate DatabaseCleaner into your Rails project. Otherwise, to add DatabaseCleaner to your project by hand, create a file `features/support/database_cleaner.rb` that looks like this: ```ruby begin require 'database_cleaner' require 'database_cleaner/cucumber' DatabaseCleaner.strategy = :truncation rescue NameError raise "You need to add database_cleaner to your Gemfile (in the :test group) if you wish to use it." end Around do |scenario, block| DatabaseCleaner.cleaning(&block) end ``` This should cover the basics of tear down between scenarios and keeping your database clean. For more examples see the section ["Why?"](#why). ## How to use with multiple ORMs Sometimes you need to use multiple ORMs in your application. You can use DatabaseCleaner to clean multiple ORMs, and multiple connections for those ORMs. ```ruby #How to specify particular orms DatabaseCleaner[:active_record].strategy = :transaction DatabaseCleaner[:mongo_mapper].strategy = :truncation #How to specify particular connections DatabaseCleaner[:active_record, { :connection => :two }] # You may also pass in the model directly: DatabaseCleaner[:active_record, { :model => ModelWithDifferentConnection }] ``` Usage beyond that remains the same with `DatabaseCleaner.start` calling any setup on the different configured connections, and `DatabaseCleaner.clean` executing afterwards. ### Configuration options
ORM How to access Notes
Active Record DatabaseCleaner[:active_record] Connection specified as :symbol keys, loaded from config/database.yml. You may also pass in the ActiveRecord model under the :model key.
Data Mapper DatabaseCleaner[:data_mapper] Connection specified as :symbol keys, loaded via Datamapper repositories
Mongo Mapper DatabaseCleaner[:mongo_mapper] Multiple connections not yet supported
Mongoid DatabaseCleaner[:mongoid] Multiple databases supported for Mongoid 3. Specify DatabaseCleaner[:mongoid, {:connection => :db_name}]
Moped DatabaseCleaner[:moped] It is necessary to configure database name with DatabaseCleaner[:moped].db = db_name otherwise name `default` will be used.
Couch Potato DatabaseCleaner[:couch_potato] Multiple connections not yet supported
Sequel DatabaseCleaner[:sequel] Multiple databases supported; specify DatabaseCleaner[:sequel, {:connection => Sequel.connect(uri)}]
Redis DatabaseCleaner[:redis] Connection specified as Redis URI
Ohm DatabaseCleaner[:ohm] Connection specified as Redis URI
Neo4j DatabaseCleaner[:neo4j] Database type and path(URI) DatabaseCleaner[:neo4j, connection: {type: :server_db, path: 'http://localhost:7475'}].
## Why? 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. After copying and pasting code to do this several times I decided to package it up as a gem and save everyone a bit of time. ## Common Errors #### DatabaseCleaner is trying to use the wrong ORM 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. Since ActiveRecord is the most common ORM used that is the first one checked for. 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: ```ruby # How to setup your ORM explicitly DatabaseCleaner[:mongoid].strategy = :truncation ``` ### STDERR is being flooded when using Postgres If you are using Postgres and have foreign key constraints, the truncation strategy will cause a lot of extra noise to appear on STDERR (in the form of "NOTICE truncate cascades" messages). To silence these warnings set the following log level in your `postgresql.conf` file: ```ruby client_min_messages = warning ``` For ActiveRecord, you add the following parameter in your database.yml file:
test:
  adapter: postgresql
  # ...
  min_messages: WARNING
### Nothing happens in JRuby with Sequel using transactions 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. ### Model fails to load with Neo4j using transactions 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. Add to your rails_helper or spec_helper after requiring database_cleaner: ```ruby require 'database_cleaner' Dir["#{Rails.root}/app/models/**/*.rb"].each do |model| load model end ``` ## Safeguards DatabaseCleaner comes with safeguards against: * Running in production (checking for `ENV`, `RACK_ENV`, and `RAILS_ENV`) * Running against a remote database (checking for a `DATABASE_URL` that does not include `localhost`) Both safeguards can be disabled separately as follows. Using environment variables: ``` export DATABASE_CLEANER_ALLOW_PRODUCTION=true export DATABASE_CLEANER_ALLOW_REMOTE_DATABASE_URL=true ``` In Ruby: ```ruby DatabaseCleaner.allow_production = true DatabaseCleaner.allow_remote_database_url = true ``` ## Debugging 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. Here's an example of using the `Rails.logger` in `env.rb`: ```ruby DatabaseCleaner.logger = Rails.logger ``` ## COPYRIGHT Copyright (c) 2014 Ben Mabey. See LICENSE for details. database_cleaner-1.7.0/Rakefile000066400000000000000000000021071326617530700164330ustar00rootroot00000000000000require "rubygems" require "bundler" Bundler.setup require 'rake' require 'rspec/core' require 'rspec/core/rake_task' RSpec::Core::RakeTask.new(:spec) do |spec| spec.pattern = FileList['spec/**/*_spec.rb'] end RSpec::Core::RakeTask.new(:rcov) do |spec| spec.pattern = 'spec/**/*_spec.rb' spec.rcov = true end begin require 'cucumber/rake/task' Cucumber::Rake::Task.new(:features) rescue LoadError puts "Cucumber is not available. In order to run features, you must: sudo gem install cucumber" end task :default => [:spec, :features] desc "Cleans the project of any tmp file that should not be included in the gemspec." task :clean do ["examples/config/database.yml", "examples/db/activerecord_one.db", "examples/db/activerecord_two.db", "examples/db/datamapper_default.db", "examples/db/datamapper_one.db", "examples/db/datamapper_two.db"].each do |f| FileUtils.rm_f(f) end %w[*.sqlite3 *.log #* *.swp *.swo].each do |pattern| `find . -name "#{pattern}" -delete` end end desc "Cleans the dir and builds the gem" task :prep => [:clean, :gemspec, :build] database_cleaner-1.7.0/TODO000066400000000000000000000001241326617530700154530ustar00rootroot00000000000000Could be more Datamapper MongoMapper multiple db support CouchDB multiple db supportdatabase_cleaner-1.7.0/VERSION.yml000066400000000000000000000000421326617530700166320ustar00rootroot00000000000000--- :major: 1 :minor: 7 :patch: 0 database_cleaner-1.7.0/cucumber.yml000066400000000000000000000000221326617530700173100ustar00rootroot00000000000000default: features database_cleaner-1.7.0/database_cleaner.gemspec000066400000000000000000000046441326617530700216000ustar00rootroot00000000000000require 'yaml' version = YAML.load_file 'VERSION.yml' Gem::Specification.new do |s| s.name = "database_cleaner" s.version = "#{version[:major]}.#{version[:minor]}.#{version[:patch]}" s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.required_ruby_version = ">= 1.9.3" s.require_paths = ["lib"] s.authors = ["Ben Mabey", "Ernesto Tagwerker"] s.description = "Strategies for cleaning databases. Can be used to ensure a clean state for testing." s.email = "ernesto@ombulabs.com" s.extra_rdoc_files = [ "LICENSE", "README.markdown", "TODO" ] s.files = [ "CONTRIBUTE.markdown", "Gemfile.lock", "History.rdoc", "README.markdown", "Rakefile", "VERSION.yml", "cucumber.yml"] s.files += Dir['lib/**/*.rb'] s.homepage = "http://github.com/DatabaseCleaner/database_cleaner" s.license = 'MIT' s.rubygems_version = "2.4.5" s.summary = "Strategies for cleaning databases. Can be used to ensure a clean state for testing." s.add_development_dependency "rake" s.add_development_dependency "bundler" s.add_development_dependency "json_pure" s.add_development_dependency "activerecord-mysql2-adapter" unless RUBY_PLATFORM =~ /java/ s.add_development_dependency "activerecord" s.add_development_dependency "datamapper" s.add_development_dependency "dm-migrations" s.add_development_dependency "dm-sqlite-adapter" s.add_development_dependency "mongoid" s.add_development_dependency "tzinfo" s.add_development_dependency "mongoid-tree" s.add_development_dependency "mongo_mapper" s.add_development_dependency "moped" s.add_development_dependency "neo4j-core" s.add_development_dependency "couch_potato" s.add_development_dependency "sequel", "~> 3.21.0" s.add_development_dependency 'ohm', '~> 0.1.3' s.add_development_dependency 'guard-rspec' s.add_development_dependency "rspec-rails", "~> 2.14.2" s.add_development_dependency "cucumber" unless RUBY_PLATFORM =~ /java/ s.add_development_dependency "mongo_ext" s.add_development_dependency "bson_ext" s.add_development_dependency 'mysql', '~> 2.9.1' s.add_development_dependency 'mysql2' s.add_development_dependency 'pg' s.add_development_dependency "sqlite3-ruby" if RUBY_VERSION < "1.9" s.add_development_dependency "sqlite3" if RUBY_VERSION >= "1.9" else s.add_development_dependency "activerecord-jdbc-adapter" end end database_cleaner-1.7.0/db/000077500000000000000000000000001326617530700153535ustar00rootroot00000000000000database_cleaner-1.7.0/db/sample.config.yml000066400000000000000000000010041326617530700206160ustar00rootroot00000000000000mysql: adapter: mysql database: database_cleaner_test username: root password: host: 127.0.0.1 port: 3306 encoding: utf8 mysql2: adapter: mysql2 database: database_cleaner_test username: root password: host: 127.0.0.1 port: 3306 encoding: utf8 postgres: adapter: postgresql database: database_cleaner_test username: postgres password: host: 127.0.0.1 encoding: unicode template: template0 sqlite3: adapter: sqlite3 database: db/test.sqlite3 pool: 5 timeout: 5000 database_cleaner-1.7.0/examples/000077500000000000000000000000001326617530700166045ustar00rootroot00000000000000database_cleaner-1.7.0/examples/Gemfile000077700000000000000000000000001326617530700216002../Gemfileustar00rootroot00000000000000database_cleaner-1.7.0/examples/Gemfile.lock000077700000000000000000000000001326617530700234562../Gemfile.lockustar00rootroot00000000000000database_cleaner-1.7.0/examples/config/000077500000000000000000000000001326617530700200515ustar00rootroot00000000000000database_cleaner-1.7.0/examples/config/database.yml.example000066400000000000000000000006001326617530700237660ustar00rootroot00000000000000#This is an example of what database.yml *should* look like (when I wrote it) #The real database.yml is generated automatically by the active record model lib (so it can be correct) two: adapter: sqlite3 database: /path/to/examples/features/support/../../db/activerecord_two.db one: adapter: sqlite3 database: /path/to/examples/features/support/../../db/activerecord_one.db database_cleaner-1.7.0/examples/config/redis.yml000066400000000000000000000001701326617530700217000ustar00rootroot00000000000000test: url: 'redis://localhost:6379/0' one: url: 'redis://localhost:6379/1' two: url: 'redis://localhost:6379/2' database_cleaner-1.7.0/examples/db/000077500000000000000000000000001326617530700171715ustar00rootroot00000000000000database_cleaner-1.7.0/examples/db/sqlite_databases_go_here000066400000000000000000000000001326617530700241020ustar00rootroot00000000000000database_cleaner-1.7.0/examples/features/000077500000000000000000000000001326617530700204225ustar00rootroot00000000000000database_cleaner-1.7.0/examples/features/example.feature000066400000000000000000000004331326617530700234320ustar00rootroot00000000000000Feature: example In order to test DataBase Cleaner Here are some scenarios that rely on the DB being clean! Scenario: dirty the db When I create a widget Then I should see 1 widget Scenario: assume a clean db When I create a widget Then I should see 1 widget database_cleaner-1.7.0/examples/features/example_multiple_db.feature000066400000000000000000000012761326617530700260200ustar00rootroot00000000000000Feature: example In order to test DataBase Cleaner Here are some scenarios that rely on the DB being clean! # Background: # Given I have setup DatabaseCleaner to clean multiple databases # Scenario: dirty the db When I create a widget in one db And I create a widget in another db Then I should see 1 widget in one db And I should see 1 widget in another db Scenario: assume a clean db When I create a widget in one db Then I should see 1 widget in one db And I should see 0 widget in another db Scenario: assume a clean db When I create a widget in another db Then I should see 0 widget in one db And I should see 1 widget in another db database_cleaner-1.7.0/examples/features/example_multiple_orm.feature000066400000000000000000000012751326617530700262270ustar00rootroot00000000000000Feature: example In order to test DataBase Cleaner Here are some scenarios that rely on the DB being clean! # Background: # Given I have setup DatabaseCleaner to clean multiple orms Scenario: dirty the db When I create a widget in one orm And I create a widget in another orm Then I should see 1 widget in one orm And I should see 1 widget in another orm Scenario: assume a clean db When I create a widget in one orm Then I should see 1 widget in one orm And I should see 0 widget in another orm Scenario: assume a clean db When I create a widget in another orm Then I should see 0 widget in one orm And I should see 1 widget in another orm database_cleaner-1.7.0/examples/features/step_definitions/000077500000000000000000000000001326617530700237705ustar00rootroot00000000000000database_cleaner-1.7.0/examples/features/step_definitions/activerecord_steps.rb000066400000000000000000000021271326617530700302070ustar00rootroot00000000000000Given /^I have setup database cleaner to clean multiple databases using activerecord$/ do #DatabaseCleaner # require "#{File.dirname(__FILE__)}/../../../lib/datamapper_models" # # DatabaseCleaner[:datamapper, {:connection => :one} ].strategy = :truncation # DatabaseCleaner[:datamapper, {:connection => :two} ].strategy = :truncation end When /^I create a widget using activerecord$/ do ActiveRecordWidget.create! end Then /^I should see ([\d]+) widget using activerecord$/ do |widget_count| ActiveRecordWidget.count.should == widget_count.to_i end When /^I create a widget in one db using activerecord$/ do ActiveRecordWidgetUsingDatabaseOne.create! end When /^I create a widget in another db using activerecord$/ do ActiveRecordWidgetUsingDatabaseTwo.create! end Then /^I should see ([\d]+) widget in one db using activerecord$/ do |widget_count| ActiveRecordWidgetUsingDatabaseOne.count.should == widget_count.to_i end Then /^I should see ([\d]+) widget in another db using activerecord$/ do |widget_count| ActiveRecordWidgetUsingDatabaseTwo.count.should == widget_count.to_i end database_cleaner-1.7.0/examples/features/step_definitions/couchpotato_steps.rb000066400000000000000000000021151326617530700300620ustar00rootroot00000000000000Given /^I have setup database cleaner to clean multiple databases using couchpotato$/ do #DatabaseCleaner # require "#{File.dirname(__FILE__)}/../../../lib/couchpotato_models" # # DatabaseCleaner[:couchpotato, {:connection => :one} ].strategy = :truncation # DatabaseCleaner[:couchpotato, {:connection => :two} ].strategy = :truncation end When /^I create a widget using couchpotato$/ do CouchPotatoWidget.create! end Then /^I should see ([\d]+) widget using couchpotato$/ do |widget_count| CouchPotatoWidget.count.should == widget_count.to_i end When /^I create a widget in one db using couchpotato$/ do CouchPotatoWidgetUsingDatabaseOne.create! end When /^I create a widget in another db using couchpotato$/ do CouchPotatoWidgetUsingDatabaseTwo.create! end Then /^I should see ([\d]+) widget in one db using couchpotato$/ do |widget_count| CouchPotatoWidgetUsingDatabaseOne.count.should == widget_count.to_i end Then /^I should see ([\d]+) widget in another db using couchpotato$/ do |widget_count| CouchPotatoWidgetUsingDatabaseTwo.count.should == widget_count.to_i end database_cleaner-1.7.0/examples/features/step_definitions/datamapper_steps.rb000066400000000000000000000022731326617530700276550ustar00rootroot00000000000000Given /^I have setup database cleaner to clean multiple databases using datamapper$/ do #DatabaseCleaner # require "#{File.dirname(__FILE__)}/../../../lib/datamapper_models" # # DatabaseCleaner[:datamapper, {:connection => :one} ].strategy = :truncation # DatabaseCleaner[:datamapper, {:connection => :two} ].strategy = :truncation end When /^I create a widget using datamapper$/ do DataMapperWidget.create! end Then /^I should see ([\d]+) widget using datamapper$/ do |widget_count| DataMapperWidget.count.should == widget_count.to_i end When /^I create a widget in one db using datamapper$/ do begin DataMapperWidgetUsingDatabaseOne.create! rescue StandardError => e BREAK = e.backtrace debugger DataMapperWidgetUsingDatabaseOne.create! end end When /^I create a widget in another db using datamapper$/ do DataMapperWidgetUsingDatabaseTwo.create! end Then /^I should see ([\d]+) widget in one db using datamapper$/ do |widget_count| DataMapperWidgetUsingDatabaseOne.count.should == widget_count.to_i end Then /^I should see ([\d]+) widget in another db using datamapper$/ do |widget_count| DataMapperWidgetUsingDatabaseTwo.count.should == widget_count.to_i end database_cleaner-1.7.0/examples/features/step_definitions/mongoid_steps.rb000066400000000000000000000013271326617530700271720ustar00rootroot00000000000000When /^I create a widget using mongoid$/ do MongoidWidget.create!( :id => rand(1000)+1000) end Then /^I should see ([\d]+) widget using mongoid$/ do |widget_count| MongoidWidget.count.should == widget_count.to_i end When /^I create a widget in one db using mongoid$/ do MongoidWidgetUsingDatabaseOne.create! end When /^I create a widget in another db using mongoid$/ do MongoidWidgetUsingDatabaseTwo.create! end Then /^I should see ([\d]+) widget in one db using mongoid$/ do |widget_count| MongoidWidgetUsingDatabaseOne.count.should == widget_count.to_i end Then /^I should see ([\d]+) widget in another db using mongoid$/ do |widget_count| MongoidWidgetUsingDatabaseTwo.count.should == widget_count.to_i end database_cleaner-1.7.0/examples/features/step_definitions/mongomapper_steps.rb000066400000000000000000000021121326617530700300530ustar00rootroot00000000000000Given /^I have setup database cleaner to clean multiple databases using mongomapper$/ do #DatabaseCleaner # require "#{File.dirname(__FILE__)}/../../../lib/datamapper_models" # # DatabaseCleaner[:datamapper, {:connection => :one} ].strategy = :truncation # DatabaseCleaner[:datamapper, {:connection => :two} ].strategy = :truncation end When /^I create a widget using mongomapper$/ do MongoMapperWidget.create! end Then /^I should see ([\d]+) widget using mongomapper$/ do |widget_count| MongoMapperWidget.count.should == widget_count.to_i end When /^I create a widget in one db using mongomapper$/ do MongoMapperWidgetUsingDatabaseOne.create! end When /^I create a widget in another db using mongomapper$/ do MongoMapperWidgetUsingDatabaseTwo.create! end Then /^I should see ([\d]+) widget in one db using mongomapper$/ do |widget_count| MongoMapperWidgetUsingDatabaseOne.count.should == widget_count.to_i end Then /^I should see ([\d]+) widget in another db using mongomapper$/ do |widget_count| MongoMapperWidgetUsingDatabaseTwo.count.should == widget_count.to_i end database_cleaner-1.7.0/examples/features/step_definitions/neo4j_steps.rb000066400000000000000000000012461326617530700265550ustar00rootroot00000000000000When /^I create a widget using neo4j$/ do Neo4jWidget.create! end Then /^I should see ([\d]+) widget using neo4j$/ do |widget_count| Neo4jWidget.count.should == widget_count.to_i end When /^I create a widget in one db using neo4j$/ do Neo4jWidgetUsingDatabaseOne.create! end When /^I create a widget in another db using neo4j$/ do Neo4jWidgetUsingDatabaseTwo.create! end Then /^I should see ([\d]+) widget in one db using neo4j$/ do |widget_count| Neo4jWidgetUsingDatabaseOne.count.should == widget_count.to_i end Then /^I should see ([\d]+) widget in another db using neo4j$/ do |widget_count| Neo4jWidgetUsingDatabaseTwo.count.should == widget_count.to_i end database_cleaner-1.7.0/examples/features/step_definitions/ohm_steps.rb000066400000000000000000000017551326617530700263260ustar00rootroot00000000000000Given /^I have setup database cleaner to clean multiple databases using ohm$/ do #DatabaseCleaner # require "#{File.dirname(__FILE__)}/../../../lib/ohm_models" # # DatabaseCleaner[:ohm, {:connection => ENV['REDIS_URL_ONE']} ].strategy = :truncation # DatabaseCleaner[:ohm, {:connection => ENV['REDIS_URL_TWO']} ].strategy = :truncation end When /^I create a widget using ohm$/ do OhmWidget.create! end Then /^I should see ([\d]+) widget using ohm$/ do |widget_count| OhmWidget.count.should == widget_count.to_i end When /^I create a widget in one db using ohm$/ do OhmWidgetUsingDatabaseOne.create! end When /^I create a widget in another db using ohm$/ do OhmWidgetUsingDatabaseTwo.create! end Then /^I should see ([\d]+) widget in one db using ohm$/ do |widget_count| OhmWidgetUsingDatabaseOne.count.should == widget_count.to_i end Then /^I should see ([\d]+) widget in another db using ohm$/ do |widget_count| OhmWidgetUsingDatabaseTwo.count.should == widget_count.to_i end database_cleaner-1.7.0/examples/features/step_definitions/redis_steps.rb000066400000000000000000000020151326617530700266370ustar00rootroot00000000000000Given /^I have setup database cleaner to clean multiple databases using redis$/ do #DatabaseCleaner # require "#{File.dirname(__FILE__)}/../../../lib/redis_models" # # DatabaseCleaner[:redis, {:connection => ENV['REDIS_URL_ONE']} ].strategy = :truncation # DatabaseCleaner[:redis, {:connection => ENV['REDIS_URL_TWO']} ].strategy = :truncation end When /^I create a widget using redis$/ do RedisWidget.create! end Then /^I should see ([\d]+) widget using redis$/ do |widget_count| RedisWidget.count.should == widget_count.to_i end When /^I create a widget in one db using redis$/ do RedisWidgetUsingDatabaseOne.create! end When /^I create a widget in another db using redis$/ do RedisWidgetUsingDatabaseTwo.create! end Then /^I should see ([\d]+) widget in one db using redis$/ do |widget_count| RedisWidgetUsingDatabaseOne.count.should == widget_count.to_i end Then /^I should see ([\d]+) widget in another db using redis$/ do |widget_count| RedisWidgetUsingDatabaseTwo.count.should == widget_count.to_i end database_cleaner-1.7.0/examples/features/step_definitions/translation_steps.rb000066400000000000000000000030671326617530700300770ustar00rootroot00000000000000When /^I create a widget$/ do step "I create a widget using #{ENV['ORM'].downcase}" end Then /^I should see 1 widget$/ do step "I should see 1 widget using #{ENV['ORM'].downcase}" end When /^I create a widget in one orm$/ do step "I create a widget using #{ENV['ORM'].downcase}" end When /^I create a widget in another orm$/ do step "I create a widget using #{ENV['ANOTHER_ORM'].downcase}" end Then /^I should see 1 widget in one orm$/ do step "I should see 1 widget using #{ENV['ORM'].downcase}" end Then /^I should see 1 widget in another orm$/ do step "I should see 1 widget using #{ENV['ANOTHER_ORM'].downcase}" end Then /^I should see 0 widget in another orm$/ do step "I should see 0 widget using #{ENV['ANOTHER_ORM'].downcase}" end Then /^I should see 0 widget in one orm$/ do step "I should see 0 widget using #{ENV['ORM'].downcase}" end When /^I create a widget in one db$/ do step "I create a widget in one db using #{ENV['ORM'].downcase}" end When /^I create a widget in another db$/ do step "I create a widget in another db using #{ENV['ORM'].downcase}" end Then /^I should see 1 widget in one db$/ do step "I should see 1 widget in one db using #{ENV['ORM'].downcase}" end Then /^I should see 1 widget in another db$/ do step "I should see 1 widget in another db using #{ENV['ORM'].downcase}" end Then /^I should see 0 widget in another db$/ do step "I should see 0 widget in another db using #{ENV['ORM'].downcase}" end Then /^I should see 0 widget in one db$/ do step "I should see 0 widget in one db using #{ENV['ORM'].downcase}" end database_cleaner-1.7.0/examples/features/support/000077500000000000000000000000001326617530700221365ustar00rootroot00000000000000database_cleaner-1.7.0/examples/features/support/env.rb000066400000000000000000000050621326617530700232560ustar00rootroot00000000000000#Hilarious as it seems, this is necessary so bundle exec cucumber works for mongoid cukeage (I'm assuming mongomapper is automatically present because its a git repo) Object.send(:remove_const, 'MongoMapper') if defined?(::MongoMapper) require 'rubygems' require 'bundler' Bundler.setup require 'rspec/expectations' #require 'ruby-debug' DB_DIR = "#{File.dirname(__FILE__)}/../../db" orm = ENV['ORM'] another_orm = ENV['ANOTHER_ORM'] strategy = ENV['STRATEGY'] multiple_db = ENV['MULTIPLE_DBS'] config = YAML::load(File.open("#{File.dirname(__FILE__)}/../../config/redis.yml")) ENV['REDIS_URL'] = config['test']['url'] ENV['REDIS_URL_ONE'] = config['one']['url'] ENV['REDIS_URL_TWO'] = config['two']['url'] if orm && strategy $:.unshift(File.dirname(__FILE__) + '/../../../lib') require 'database_cleaner' require 'database_cleaner/cucumber' require "#{File.dirname(__FILE__)}/../../lib/#{orm.downcase}_models" if another_orm require "#{File.dirname(__FILE__)}/../../lib/#{another_orm.downcase}_models" end if multiple_db DatabaseCleaner.app_root = "#{File.dirname(__FILE__)}/../.." orm_sym = orm.gsub(/(.)([A-Z]+)/,'\1_\2').downcase.to_sym case orm_sym when :mongo_mapper DatabaseCleaner[ orm_sym, {:connection => 'database_cleaner_test_one'} ].strategy = strategy.to_sym DatabaseCleaner[ orm_sym, {:connection => 'database_cleaner_test_two'} ].strategy = strategy.to_sym when :redis, :ohm DatabaseCleaner[ orm_sym, {:connection => ENV['REDIS_URL_ONE']} ].strategy = strategy.to_sym DatabaseCleaner[ orm_sym, {:connection => ENV['REDIS_URL_TWO']} ].strategy = strategy.to_sym when :active_record DatabaseCleaner[:active_record, {:model => ActiveRecordWidgetUsingDatabaseOne} ].strategy = strategy.to_sym DatabaseCleaner[:active_record, {:model => ActiveRecordWidgetUsingDatabaseTwo} ].strategy = strategy.to_sym else DatabaseCleaner[ orm_sym, {:connection => :one} ].strategy = strategy.to_sym DatabaseCleaner[ orm_sym, {:connection => :two} ].strategy = strategy.to_sym end elsif another_orm DatabaseCleaner[ orm.gsub(/(.)([A-Z]+)/,'\1_\2').downcase.to_sym ].strategy = strategy.to_sym DatabaseCleaner[ another_orm.gsub(/(.)([A-Z]+)/,'\1_\2').downcase.to_sym ].strategy = strategy.to_sym else DatabaseCleaner.strategy = strategy.to_sym unless strategy == "default" end else raise "Run 'ORM=ActiveRecord|DataMapper|MongoMapper|CouchPotato|Ohm|Redis [ANOTHER_ORM=...] [MULTIPLE_DBS=true] STRATEGY=transaction|truncation|default cucumber examples/features'" end database_cleaner-1.7.0/examples/lib/000077500000000000000000000000001326617530700173525ustar00rootroot00000000000000database_cleaner-1.7.0/examples/lib/activerecord_models.rb000066400000000000000000000030441326617530700237150ustar00rootroot00000000000000require 'active_record' databases_config = { "one" => {"adapter" => "#{"jdbc" if defined?(JRUBY_VERSION)}sqlite3", "database" => "#{DB_DIR}/activerecord_one.db"}, "two" => {"adapter" => "#{"jdbc" if defined?(JRUBY_VERSION)}sqlite3", "database" => "#{DB_DIR}/activerecord_two.db"} } File.open("#{File.dirname(__FILE__)}/../config/database.yml", 'w') do |file| file.write(YAML.dump(databases_config)) end ["two","one"].each do |db| ActiveRecord::Base.establish_connection(databases_config[db]) ActiveRecord::Base.connection.execute('DROP TABLE IF EXISTS "active_record_widgets"') ActiveRecord::Base.connection.execute('DROP TABLE IF EXISTS "active_record_widget_using_database_ones"') ActiveRecord::Base.connection.execute('DROP TABLE IF EXISTS "active_record_widget_using_database_twos"') ActiveRecord::Schema.define(:version => 1) do create_table :active_record_widgets do |t| t.string :name end create_table :active_record_widget_using_database_ones do |t| t.string :name end create_table :active_record_widget_using_database_twos do |t| t.string :name end end end class ActiveRecordWidget < ActiveRecord::Base end class ActiveRecordWidgetUsingDatabaseOne < ActiveRecord::Base establish_connection(:adapter => "#{"jdbc" if defined?(JRUBY_VERSION)}sqlite3", :database => "#{DB_DIR}/activerecord_one.db") end class ActiveRecordWidgetUsingDatabaseTwo < ActiveRecord::Base establish_connection(:adapter => "#{"jdbc" if defined?(JRUBY_VERSION)}sqlite3", :database => "#{DB_DIR}/activerecord_two.db") end database_cleaner-1.7.0/examples/lib/couchpotato_models.rb000066400000000000000000000022431326617530700235730ustar00rootroot00000000000000require 'couch_potato' require 'json/pure' unless defined? ::JSON ::CouchPotato::Config.database_name = 'couch_potato_test' class CouchPotatoWidget include CouchPotato::Persistence property :name view :by_name, :key => :name # mimic the AR interface used in example_steps def self.create!(attrs = {}) CouchPotato.database.save(self.new) end def self.count CouchPotato.database.view(self.by_name).size end end class CouchPotatoWidgetUsingDatabaseOne include CouchPotato::Persistence database_name = 'couch_potato_test_one' property :name view :by_name, :key => :name # mimic the AR interface used in example_steps def self.create!(attrs = {}) CouchPotato.database.save(self.new) end def self.count CouchPotato.database.view(self.by_name).size end end class CouchPotatoWidgetUsingDatabaseTwo include CouchPotato::Persistence database_name = 'couch_potato_test_two' property :name view :by_name, :key => :name # mimic the AR interface used in example_steps def self.create!(attrs = {}) CouchPotato.database.save(self.new) end def self.count CouchPotato.database.view(self.by_name).size end end database_cleaner-1.7.0/examples/lib/datamapper_models.rb000066400000000000000000000021141326617530700233560ustar00rootroot00000000000000require "dm-core" require "dm-transactions" #Datamapper 1.0 requires you to require dm-migrations to automigrate require "dm-migrations" # only to please activerecord API used in database_cleaner/examples/features/step_definitions # yes, i know that's lazy ... require "dm-validations" require "dm-aggregates" DataMapper.setup(:default, "sqlite3:#{DB_DIR}/datamapper_default.db") DataMapper.setup(:one, "sqlite3:#{DB_DIR}/datamapper_one.db") DataMapper.setup(:two, "sqlite3:#{DB_DIR}/datamapper_two.db") class DataMapperWidget include DataMapper::Resource property :id, Serial property :name, String end class DataMapperWidgetUsingDatabaseOne include DataMapper::Resource def self.default_repository_name :one end property :id, Serial property :name, String end class DataMapperWidgetUsingDatabaseTwo include DataMapper::Resource def self.default_repository_name :two end property :id, Serial property :name, String end DataMapperWidget.auto_migrate! DataMapperWidgetUsingDatabaseOne.auto_migrate! DataMapperWidgetUsingDatabaseTwo.auto_migrate! database_cleaner-1.7.0/examples/lib/mongoid_models.rb000066400000000000000000000014521326617530700227000ustar00rootroot00000000000000require 'mongoid' Mongoid.configure do |config| config.master = Mongo::Connection.new.db('database_cleaner_test') end class MongoidWidget include Mongoid::Document field :id, :type => Integer field :name class << self #mongoid doesn't seem to provide this... def create!(*args) new(*args).save! end end end class MongoidWidgetUsingDatabaseOne include Mongoid::Document field :id, :type => Integer field :name class << self #mongoid doesn't seem to provide this... def create!(*args) new(*args).save! end end end class MongoidWidgetUsingDatabaseTwo include Mongoid::Document field :id, :type => Integer field :name class << self #mongoid doesn't seem to provide this... def create!(*args) new(*args).save! end end end database_cleaner-1.7.0/examples/lib/mongomapper_models.rb000066400000000000000000000020311326617530700235620ustar00rootroot00000000000000require 'mongo_mapper' ::MongoMapper.connection = Mongo::Connection.new('127.0.0.1') ::MongoMapper.database = 'database_cleaner_test' class MongoMapperWidget include MongoMapper::Document key :id, Integer key :name, String class << self #mongomapper doesn't seem to provide this... def create!(*args) new(*args).save! end end end class MongoMapperWidgetUsingDatabaseOne include MongoMapper::Document connection = Mongo::Connection.new('127.0.0.1') set_database_name = 'database_cleaner_test_one' key :id, Integer key :name, String class << self #mongomapper doesn't seem to provide this... def create!(*args) new(*args).save! end end end class MongoMapperWidgetUsingDatabaseTwo include MongoMapper::Document connection = Mongo::Connection.new('127.0.0.1') set_database_name = 'database_cleaner_test_two' key :id, Integer key :name, String class << self #mongomapper doesn't seem to provide this... def create!(*args) new(*args).save! end end end database_cleaner-1.7.0/examples/lib/neo4j_models.rb000066400000000000000000000004521326617530700222620ustar00rootroot00000000000000require 'neo4j-core' class Neo4jWidget < Neo4j::Node def self.create!(*args) create(*args) end def self.count Neo4j::Session.query.match('n').pluck('COUNT(n)').first end end class Neo4jWidgetUsingDatabaseOne < Neo4jWidget end class Neo4jWidgetUsingDatabaseTwo < Neo4jWidget end database_cleaner-1.7.0/examples/lib/ohm_models.rb000066400000000000000000000013401326617530700220230ustar00rootroot00000000000000require 'ohm' Ohm.connect :url => ENV['REDIS_URL'] class OhmWidget < Ohm::Model attribute :name def self.create!(attrs = {}) new({:name => 'some widget'}.merge(attrs)).save end def self.count all.count end end class OhmWidgetUsingDatabaseOne < Ohm::Model connect :url => ENV['REDIS_URL_ONE'] attribute :name def self.create!(attrs = {}) new({:name => 'a widget using database one'}.merge(attrs)).save end def self.count all.count end end class OhmWidgetUsingDatabaseTwo < Ohm::Model connect :url => ENV['REDIS_URL_TWO'] attribute :name def self.create!(attrs = {}) new({:name => 'a widget using database two'}.merge(attrs)).save end def self.count all.count end end database_cleaner-1.7.0/examples/lib/redis_models.rb000066400000000000000000000022661326617530700223560ustar00rootroot00000000000000require 'redis' class RedisWidget def self.redis threaded ||= Redis.new end def self.redis=(connection) threaded = connection end def self.threaded Thread.current[self.class.to_s] ||= {} end def initialize(options = {}) options = options.dup @name = options[:name] end def connection self.class.redis end def save unless connection.get(self.class.to_s + ':id') @id = 0 connection.set(self.class.to_s + ':id', @id) end @id = connection.incr(self.class.to_s + ':id') connection.set(self.class.to_s + ':%d:name' % @id, @name) end def self.count self.redis.keys(self.to_s + '*name').size end def self.create! new(:name => 'some widget').save end end class RedisWidgetUsingDatabaseOne < RedisWidget def self.redis threaded[self.class.to_s] ||= Redis.new :url => ENV['REDIS_URL_ONE'] end def self.create! new(:name => 'a widget using database one').save end end class RedisWidgetUsingDatabaseTwo < RedisWidget def self.redis threaded[self.class.to_s] ||= Redis.new :url => ENV['REDIS_URL_TWO'] end def self.create! new(:name => 'a widget using database two').save end end database_cleaner-1.7.0/examples/lib/sequel_models.rb000066400000000000000000000002361326617530700225410ustar00rootroot00000000000000require 'sequel' db = Sequel.sqlite # memory database db.run 'DROP TABLE IF EXISTS "sequel_widgets"' db.create_table :sequel_widgets do String :name end database_cleaner-1.7.0/features/000077500000000000000000000000001326617530700166045ustar00rootroot00000000000000database_cleaner-1.7.0/features/cleaning.feature000066400000000000000000000016461326617530700217500ustar00rootroot00000000000000Feature: database cleaning In order to ease example and feature writing As a developer I want to have my database in a clean state Scenario Outline: ruby app Given I am using And the cleaning strategy When I run my scenarios that rely on a clean database Then I should see all green Examples: | ORM | Strategy | | ActiveRecord | transaction | | ActiveRecord | truncation | | ActiveRecord | deletion | | DataMapper | transaction | | DataMapper | truncation | | Sequel | transaction | | Sequel | truncation | | Sequel | deletion | | MongoMapper | truncation | | Mongoid | truncation | | CouchPotato | truncation | | Redis | truncation | | Ohm | truncation | | Neo4j | deletion | | Neo4j | truncation | | Neo4j | transaction | database_cleaner-1.7.0/features/cleaning_default_strategy.feature000066400000000000000000000010701326617530700253650ustar00rootroot00000000000000Feature: database cleaning In order to ease example and feature writing As a developer I want to have my database in a clean state with default strategy Scenario Outline: ruby app Given I am using And the default cleaning strategy When I run my scenarios that rely on a clean database Then I should see all green Examples: | ORM | | ActiveRecord | | DataMapper | | Sequel | | MongoMapper | | Mongoid | | CouchPotato | | Redis | | Ohm | | Neo4j | database_cleaner-1.7.0/features/cleaning_multiple_dbs.feature000066400000000000000000000012271326617530700245060ustar00rootroot00000000000000Feature: multiple database cleaning In order to ease example and feature writing As a developer I want to have my databases in a clean state Scenario Outline: ruby app Given I am using And the cleaning strategy When I run my scenarios that rely on clean databases Then I should see all green Examples: | ORM | Strategy | | ActiveRecord | truncation | | ActiveRecord | deletion | | DataMapper | truncation | | Sequel | truncation | | MongoMapper | truncation | | DataMapper | transaction | | ActiveRecord | transaction | | Sequel | transaction | database_cleaner-1.7.0/features/cleaning_multiple_orms.feature000066400000000000000000000044311326617530700247160ustar00rootroot00000000000000Feature: database cleaning using multiple ORMs In order to ease example and feature writing As a developer I want to have my database in a clean state Scenario Outline: ruby app Given I am using and When I run my scenarios that rely on clean databases using multiple orms Then I should see all green Examples: | ORM1 | ORM2 | | ActiveRecord | DataMapper | | ActiveRecord | Sequel | | ActiveRecord | MongoMapper | | ActiveRecord | Mongoid | | ActiveRecord | CouchPotato | | ActiveRecord | Ohm | | ActiveRecord | Redis | | DataMapper | ActiveRecord | | DataMapper | Sequel | | DataMapper | MongoMapper | | DataMapper | Mongoid | | DataMapper | CouchPotato | | DataMapper | Ohm | | DataMapper | Redis | | Sequel | ActiveRecord | | Sequel | DataMapper | | Sequel | MongoMapper | | Sequel | Mongoid | | Sequel | CouchPotato | | Sequel | Ohm | | Sequel | Redis | | MongoMapper | ActiveRecord | | MongoMapper | DataMapper | | MongoMapper | Sequel | | MongoMapper | Mongoid | | MongoMapper | CouchPotato | | MongoMapper | Ohm | | MongoMapper | Redis | | CouchPotato | ActiveRecord | | CouchPotato | DataMapper | | CouchPotato | Sequel | | CouchPotato | MongoMapper | | CouchPotato | Mongoid | | CouchPotato | Ohm | | CouchPotato | Redis | | Ohm | ActiveRecord | | Ohm | DataMapper | | Ohm | Sequel | | Ohm | MongoMapper | | Ohm | Mongoid | | Ohm | CouchPotato | | Redis | ActiveRecord | | Redis | DataMapper | | Redis | Sequel | | Redis | MongoMapper | | Redis | Mongoid | | Redis | CouchPotato | | Redis | Ohm | | Neo4j | ActiveRecord | | Neo4j | DataMapper | | Neo4j | Sequel | | Neo4j | Redis | | Neo4j | Ohm | | Neo4j | MongoMapper | database_cleaner-1.7.0/features/step_definitions/000077500000000000000000000000001326617530700221525ustar00rootroot00000000000000database_cleaner-1.7.0/features/step_definitions/database_cleaner_steps.rb000066400000000000000000000017541326617530700271610ustar00rootroot00000000000000orms_pattern = /(ActiveRecord|DataMapper|Sequel|MongoMapper|Mongoid|CouchPotato|Redis|Ohm|Neo4j)/ Given /^I am using #{orms_pattern}$/ do |orm| @feature_runner = FeatureRunner.new @feature_runner.orm = orm end Given /^I am using #{orms_pattern} and #{orms_pattern}$/ do |orm1,orm2| @feature_runner = FeatureRunner.new @feature_runner.orm = orm1 @feature_runner.another_orm = orm2 end Given /^the (.+) cleaning strategy$/ do |strategy| @feature_runner.strategy = strategy end When "I run my scenarios that rely on a clean database" do @feature_runner.go 'example' end When "I run my scenarios that rely on clean databases" do @feature_runner.multiple_databases = true @feature_runner.go 'example_multiple_db' end When "I run my scenarios that rely on clean databases using multiple orms" do @feature_runner.go 'example_multiple_orm' end Then "I should see all green" do fail "Feature failed with :#{@feature_runner.output}" unless @feature_runner.exit_status == 0 end database_cleaner-1.7.0/features/support/000077500000000000000000000000001326617530700203205ustar00rootroot00000000000000database_cleaner-1.7.0/features/support/env.rb000066400000000000000000000001631326617530700214350ustar00rootroot00000000000000$LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../lib') require 'database_cleaner' require 'rspec/expectations' database_cleaner-1.7.0/features/support/feature_runner.rb000066400000000000000000000014771326617530700237020ustar00rootroot00000000000000class FeatureRunner attr_accessor :orm attr_accessor :another_orm attr_accessor :multiple_databases attr_accessor :strategy attr_accessor :exit_status attr_accessor :output def strategy @strategy || 'truncation' end def go(feature) full_dir ||= File.expand_path(File.dirname(__FILE__) + "/../../examples/") Dir.chdir(full_dir) do ENV['ORM'] = orm ENV['STRATEGY'] = strategy if another_orm ENV['ANOTHER_ORM'] = another_orm else ENV['ANOTHER_ORM'] = nil end if multiple_databases ENV['MULTIPLE_DBS'] = "true" else ENV['MULTIPLE_DBS'] = nil end self.output = `#{"jruby -S " if defined?(JRUBY_VERSION)}cucumber features/#{feature}.feature` self.exit_status = $?.exitstatus end end end database_cleaner-1.7.0/lib/000077500000000000000000000000001326617530700155345ustar00rootroot00000000000000database_cleaner-1.7.0/lib/database_cleaner.rb000066400000000000000000000005511326617530700213170ustar00rootroot00000000000000$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__))) unless $LOAD_PATH.include?(File.expand_path(File.dirname(__FILE__))) require 'database_cleaner/configuration' module DatabaseCleaner class << self attr_accessor :allow_remote_database_url, :allow_production def can_detect_orm? DatabaseCleaner::Base.autodetect_orm end end end database_cleaner-1.7.0/lib/database_cleaner/000077500000000000000000000000001326617530700207715ustar00rootroot00000000000000database_cleaner-1.7.0/lib/database_cleaner/active_record/000077500000000000000000000000001326617530700236025ustar00rootroot00000000000000database_cleaner-1.7.0/lib/database_cleaner/active_record/base.rb000066400000000000000000000053421326617530700250450ustar00rootroot00000000000000require 'database_cleaner/generic/base' require 'active_record' require 'erb' module DatabaseCleaner module ActiveRecord def self.available_strategies %w[truncation transaction deletion] end def self.config_file_location=(path) @config_file_location = path end def self.config_file_location @config_file_location ||= "#{DatabaseCleaner.app_root}/config/database.yml" end module Base include ::DatabaseCleaner::Generic::Base attr_accessor :connection_hash def db=(desired_db) @db = desired_db load_config end def db @db ||= super end def load_config if self.db != :default && self.db.is_a?(Symbol) && File.file?(ActiveRecord.config_file_location) connection_details = YAML::load(ERB.new(IO.read(ActiveRecord.config_file_location)).result) @connection_hash = valid_config(connection_details)[self.db.to_s] end end def valid_config(connection_file) if !::ActiveRecord::Base.configurations.nil? && !::ActiveRecord::Base.configurations.empty? if connection_file != ::ActiveRecord::Base.configurations return ::ActiveRecord::Base.configurations end end connection_file end def connection_class @connection_class ||= if db && !db.is_a?(Symbol) db elsif connection_hash lookup_from_connection_pool || establish_connection else ::ActiveRecord::Base end end def self.migration_table_name if ::ActiveRecord::VERSION::MAJOR < 5 ::ActiveRecord::Migrator.schema_migrations_table_name else ::ActiveRecord::SchemaMigration.table_name end end def self.exclusion_condition(column_name) result = " #{column_name} <> '#{::DatabaseCleaner::ActiveRecord::Base.migration_table_name}' " if ::ActiveRecord::VERSION::MAJOR >= 5 result += " AND #{column_name} <> '#{::ActiveRecord::Base.internal_metadata_table_name}' " end result end private def lookup_from_connection_pool if ::ActiveRecord::Base.respond_to?(:descendants) database_name = connection_hash["database"] || connection_hash[:database] models = ::ActiveRecord::Base.descendants models.detect { |m| m.connection_pool.spec.config[:database] == database_name } end end def establish_connection ::ActiveRecord::Base.establish_connection(connection_hash) ::ActiveRecord::Base end end end end database_cleaner-1.7.0/lib/database_cleaner/active_record/deletion.rb000066400000000000000000000077671326617530700257530ustar00rootroot00000000000000require 'active_record/base' require 'active_record/connection_adapters/abstract_adapter' require "database_cleaner/generic/truncation" require 'database_cleaner/active_record/base' require 'database_cleaner/active_record/truncation' module DatabaseCleaner module ConnectionAdapters module AbstractDeleteAdapter def delete_table(table_name) raise NotImplementedError end end module GenericDeleteAdapter def delete_table(table_name) execute("DELETE FROM #{quote_table_name(table_name)};") end end module OracleDeleteAdapter def delete_table(table_name) execute("DELETE FROM #{quote_table_name(table_name)}") end end end end module ActiveRecord module ConnectionAdapters AbstractAdapter.class_eval { include DatabaseCleaner::ConnectionAdapters::AbstractDeleteAdapter } JdbcAdapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::GenericDeleteAdapter } if defined?(JdbcAdapter) AbstractMysqlAdapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::GenericDeleteAdapter } if defined?(AbstractMysqlAdapter) Mysql2Adapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::GenericDeleteAdapter } if defined?(Mysql2Adapter) SQLiteAdapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::GenericDeleteAdapter } if defined?(SQLiteAdapter) SQLite3Adapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::GenericDeleteAdapter } if defined?(SQLite3Adapter) PostgreSQLAdapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::GenericDeleteAdapter } if defined?(PostgreSQLAdapter) IBM_DBAdapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::GenericDeleteAdapter } if defined?(IBM_DBAdapter) SQLServerAdapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::GenericDeleteAdapter } if defined?(SQLServerAdapter) OracleEnhancedAdapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::OracleDeleteAdapter } if defined?(OracleEnhancedAdapter) end end module DatabaseCleaner::ActiveRecord module SelectiveTruncation def tables_to_truncate(connection) if information_schema_exists?(connection) (@only || tables_with_new_rows(connection)) - @tables_to_exclude else super end end def tables_with_new_rows(connection) @db_name ||= connection.instance_variable_get('@config')[:database] stats = table_stats_query(connection, @db_name) if stats != '' connection.exec_query(stats).inject([]) {|all, stat| all << stat['table_name'] if stat['exact_row_count'] > 0; all } else [] end end def table_stats_query(connection, db_name) if @cache_tables && !@table_stats_query.nil? return @table_stats_query else tables = connection.select_values(<<-SQL) SELECT table_name FROM information_schema.tables WHERE table_schema = '#{db_name}' AND #{::DatabaseCleaner::ActiveRecord::Base.exclusion_condition('table_name')}; SQL queries = tables.map do |table| "SELECT #{connection.quote(table)} AS table_name, COUNT(*) AS exact_row_count FROM #{connection.quote_table_name(table)}" end @table_stats_query = queries.join(' UNION ') end end def information_schema_exists? connection return false unless connection.is_a? ActiveRecord::ConnectionAdapters::Mysql2Adapter @information_schema_exists ||= begin connection.execute("SELECT 1 FROM information_schema.tables") true rescue false end end end class Deletion < Truncation if defined?(ActiveRecord::ConnectionAdapters::Mysql2Adapter) include SelectiveTruncation end def clean connection = connection_class.connection connection.disable_referential_integrity do tables_to_truncate(connection).each do |table_name| connection.delete_table table_name end end end end end database_cleaner-1.7.0/lib/database_cleaner/active_record/transaction.rb000066400000000000000000000035661326617530700264660ustar00rootroot00000000000000require 'database_cleaner/active_record/base' require 'database_cleaner/generic/transaction' module DatabaseCleaner::ActiveRecord class Transaction include ::DatabaseCleaner::ActiveRecord::Base include ::DatabaseCleaner::Generic::Transaction def start # Hack to make sure that the connection is properly setup for # the clean code. connection_class.connection.transaction{ } if connection_maintains_transaction_count? if connection_class.connection.respond_to?(:increment_open_transactions) connection_class.connection.increment_open_transactions else connection_class.__send__(:increment_open_transactions) end end if connection_class.connection.respond_to?(:begin_transaction) connection_class.connection.begin_transaction :joinable => false else connection_class.connection.begin_db_transaction end end def clean connection_class.connection_pool.connections.each do |connection| next unless connection.open_transactions > 0 if connection.respond_to?(:rollback_transaction) connection.rollback_transaction else connection.rollback_db_transaction end # The below is for handling after_commit hooks.. see https://github.com/bmabey/database_cleaner/issues/99 if connection.respond_to?(:rollback_transaction_records, true) connection.send(:rollback_transaction_records, true) end if connection_maintains_transaction_count? if connection.respond_to?(:decrement_open_transactions) connection.decrement_open_transactions else connection_class.__send__(:decrement_open_transactions) end end end end def connection_maintains_transaction_count? ActiveRecord::VERSION::MAJOR < 4 end end end database_cleaner-1.7.0/lib/database_cleaner/active_record/truncation.rb000066400000000000000000000225351326617530700263240ustar00rootroot00000000000000require 'active_record/base' require 'active_record/connection_adapters/abstract_adapter' #Load available connection adapters %w( abstract_mysql_adapter postgresql_adapter sqlite3_adapter mysql_adapter mysql2_adapter ).each do |known_adapter| begin require "active_record/connection_adapters/#{known_adapter}" rescue LoadError end end require "database_cleaner/generic/truncation" require 'database_cleaner/active_record/base' module DatabaseCleaner module ConnectionAdapters module AbstractAdapter # used to be called views but that can clash with gems like schema_plus # this gem is not meant to be exposing such an extra interface any way def database_cleaner_view_cache @views ||= select_values("select table_name from information_schema.views where table_schema = '#{current_database}'") rescue [] end def database_cleaner_table_cache # the adapters don't do caching (#130) but we make the assumption that the list stays the same in tests @database_cleaner_tables ||= ::ActiveRecord::VERSION::MAJOR >= 5 ? data_sources : tables end def truncate_table(table_name) raise NotImplementedError end def truncate_tables(tables) tables.each do |table_name| self.truncate_table(table_name) end end end module AbstractMysqlAdapter def truncate_table(table_name) execute("TRUNCATE TABLE #{quote_table_name(table_name)};") end def truncate_tables(tables) tables.each { |t| truncate_table(t) } end def pre_count_truncate_tables(tables, options = {:reset_ids => true}) filter = options[:reset_ids] ? method(:has_been_used?) : method(:has_rows?) truncate_tables(tables.select(&filter)) end private def row_count(table) # Patch for MysqlAdapter with ActiveRecord 3.2.7 later # select_value("SELECT 1") #=> "1" select_value("SELECT EXISTS (SELECT 1 FROM #{quote_table_name(table)} LIMIT 1)").to_i end # Returns a boolean indicating if the given table has an auto-inc number higher than 0. # Note, this is different than an empty table since an table may populated, the index increased, # but then the table is cleaned. In other words, this function tells us if the given table # was ever inserted into. def has_been_used?(table) if has_rows?(table) true else # Patch for MysqlAdapter with ActiveRecord 3.2.7 later # select_value("SELECT 1") #=> "1" select_value(<<-SQL).to_i > 1 # returns nil if not present SELECT Auto_increment FROM information_schema.tables WHERE table_name='#{table}'; SQL end end def has_rows?(table) row_count(table) > 0 end end module IBM_DBAdapter def truncate_table(table_name) execute("TRUNCATE #{quote_table_name(table_name)} IMMEDIATE") end end module SQLiteAdapter def delete_table(table_name) execute("DELETE FROM #{quote_table_name(table_name)};") if uses_sequence execute("DELETE FROM sqlite_sequence where name = '#{table_name}';") end end alias truncate_table delete_table def truncate_tables(tables) tables.each { |t| truncate_table(t) } end private # Returns a boolean indicating if the SQLite database is using the sqlite_sequence table. def uses_sequence select_value("SELECT name FROM sqlite_master WHERE type='table' AND name='sqlite_sequence';") end end module TruncateOrDelete def truncate_table(table_name) begin execute("TRUNCATE TABLE #{quote_table_name(table_name)};") rescue ::ActiveRecord::StatementInvalid execute("DELETE FROM #{quote_table_name(table_name)};") end end end module OracleAdapter def truncate_table(table_name) execute("TRUNCATE TABLE #{quote_table_name(table_name)}") end end module PostgreSQLAdapter def db_version @db_version ||= postgresql_version end def cascade @cascade ||= db_version >= 80200 ? 'CASCADE' : '' end def restart_identity @restart_identity ||= db_version >= 80400 ? 'RESTART IDENTITY' : '' end def truncate_table(table_name) truncate_tables([table_name]) end def truncate_tables(table_names) return if table_names.nil? || table_names.empty? execute("TRUNCATE TABLE #{table_names.map{|name| quote_table_name(name)}.join(', ')} #{restart_identity} #{cascade};") end def pre_count_truncate_tables(tables, options = {:reset_ids => true}) filter = options[:reset_ids] ? method(:has_been_used?) : method(:has_rows?) truncate_tables(tables.select(&filter)) end def database_cleaner_table_cache # AR returns a list of tables without schema but then returns a # migrations table with the schema. There are other problems, too, # with using the base list. If a table exists in multiple schemas # within the search path, truncation without the schema name could # result in confusing, if not unexpected results. @database_cleaner_tables ||= tables_with_schema end private # Returns a boolean indicating if the given table has an auto-inc number higher than 0. # Note, this is different than an empty table since an table may populated, the index increased, # but then the table is cleaned. In other words, this function tells us if the given table # was ever inserted into. def has_been_used?(table) return has_rows?(table) unless has_sequence?(table) cur_val = select_value("SELECT currval('#{table}_id_seq');").to_i rescue 0 cur_val > 0 end def has_sequence?(table) select_value("SELECT true FROM pg_class WHERE relname = '#{table}_id_seq';") end def has_rows?(table) select_value("SELECT true FROM #{table} LIMIT 1;") end def tables_with_schema rows = select_rows <<-_SQL SELECT schemaname || '.' || tablename FROM pg_tables WHERE tablename !~ '_prt_' AND #{::DatabaseCleaner::ActiveRecord::Base.exclusion_condition('tablename')} AND schemaname = ANY (current_schemas(false)) _SQL rows.collect { |result| result.first } end end end end module ActiveRecord module ConnectionAdapters #Apply adapter decoraters where applicable (adapter should be loaded) AbstractAdapter.class_eval { include DatabaseCleaner::ConnectionAdapters::AbstractAdapter } if defined?(JdbcAdapter) if defined?(OracleJdbcConnection) JdbcAdapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::OracleAdapter } else JdbcAdapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::TruncateOrDelete } end end AbstractMysqlAdapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::AbstractMysqlAdapter } if defined?(AbstractMysqlAdapter) Mysql2Adapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::AbstractMysqlAdapter } if defined?(Mysql2Adapter) MysqlAdapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::AbstractMysqlAdapter } if defined?(MysqlAdapter) SQLiteAdapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::SQLiteAdapter } if defined?(SQLiteAdapter) SQLite3Adapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::SQLiteAdapter } if defined?(SQLite3Adapter) PostgreSQLAdapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::PostgreSQLAdapter } if defined?(PostgreSQLAdapter) IBM_DBAdapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::IBM_DBAdapter } if defined?(IBM_DBAdapter) SQLServerAdapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::TruncateOrDelete } if defined?(SQLServerAdapter) OracleEnhancedAdapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::OracleAdapter } if defined?(OracleEnhancedAdapter) end end module DatabaseCleaner::ActiveRecord class Truncation include ::DatabaseCleaner::ActiveRecord::Base include ::DatabaseCleaner::Generic::Truncation def clean connection = connection_class.connection connection.disable_referential_integrity do if pre_count? && connection.respond_to?(:pre_count_truncate_tables) connection.pre_count_truncate_tables(tables_to_truncate(connection), {:reset_ids => reset_ids?}) else connection.truncate_tables(tables_to_truncate(connection)) end end end private def tables_to_truncate(connection) tables_in_db = cache_tables? ? connection.database_cleaner_table_cache : connection.tables to_reject = (@tables_to_exclude + connection.database_cleaner_view_cache) (@only || tables_in_db).reject do |table| if ( m = table.match(/([^.]+)$/) ) to_reject.include?(m[1]) else false end end end # overwritten def migration_storage_names [::DatabaseCleaner::ActiveRecord::Base.migration_table_name] end def cache_tables? !!@cache_tables end def pre_count? @pre_count == true end def reset_ids? @reset_ids != false end end end database_cleaner-1.7.0/lib/database_cleaner/base.rb000066400000000000000000000101441326617530700222300ustar00rootroot00000000000000require 'database_cleaner/null_strategy' require 'database_cleaner/safeguard' module DatabaseCleaner class Base include Comparable def <=>(other) (self.orm <=> other.orm) == 0 ? self.db <=> other.db : self.orm <=> other.orm end def initialize(desired_orm = nil,opts = {}) if [:autodetect, nil, "autodetect"].include?(desired_orm) autodetect else self.orm = desired_orm end self.db = opts[:connection] || opts[:model] if opts.has_key?(:connection) || opts.has_key?(:model) set_default_orm_strategy Safeguard.new.run end def db=(desired_db) self.strategy_db = desired_db @db = desired_db end def strategy_db=(desired_db) if strategy.respond_to? :db= strategy.db = desired_db elsif desired_db!= :default raise ArgumentError, "You must provide a strategy object that supports non default databases when you specify a database" end end def db @db ||= :default end def create_strategy(*args) strategy, *strategy_args = args orm_strategy(strategy).new(*strategy_args) end def clean_with(*args) strategy = create_strategy(*args) set_strategy_db strategy, self.db strategy.clean strategy end alias clean_with! clean_with def set_strategy_db(strategy, desired_db) if strategy.respond_to? :db= strategy.db = desired_db elsif desired_db != :default raise ArgumentError, "You must provide a strategy object that supports non default databases when you specify a database" end end def strategy=(args) strategy, *strategy_args = args if strategy.is_a?(Symbol) @strategy = create_strategy(*args) elsif strategy_args.empty? @strategy = strategy else raise ArgumentError, "You must provide a strategy object, or a symbol for a known strategy along with initialization params." end set_strategy_db @strategy, self.db @strategy end def strategy @strategy ||= NullStrategy end def orm=(desired_orm) @orm = desired_orm.to_sym end def orm @orm || autodetect end def start strategy.start end def clean strategy.clean end alias clean! clean def cleaning(&block) strategy.cleaning(&block) end def auto_detected? !!@autodetected end def autodetect_orm if defined? ::ActiveRecord :active_record elsif defined? ::DataMapper :data_mapper elsif defined? ::MongoMapper :mongo_mapper elsif defined? ::Mongoid :mongoid elsif defined? ::CouchPotato :couch_potato elsif defined? ::Sequel :sequel elsif defined? ::Moped :moped elsif defined? ::Ohm :ohm elsif defined? ::Redis :redis elsif defined? ::Neo4j :neo4j end end private def orm_module ::DatabaseCleaner.orm_module(orm) end def orm_strategy(strategy) require "database_cleaner/#{orm.to_s}/#{strategy.to_s}" orm_module.const_get(strategy.to_s.capitalize) rescue LoadError if orm_module.respond_to? :available_strategies raise UnknownStrategySpecified, "The '#{strategy}' strategy does not exist for the #{orm} ORM! Available strategies: #{orm_module.available_strategies.join(', ')}" else raise UnknownStrategySpecified, "The '#{strategy}' strategy does not exist for the #{orm} ORM!" end end def autodetect @autodetected = true @orm ||= autodetect_orm || raise(NoORMDetected, "No known ORM was detected! Is ActiveRecord, DataMapper, Sequel, MongoMapper, Mongoid, Moped, or CouchPotato, Redis or Ohm loaded?") end def set_default_orm_strategy case orm when :active_record, :data_mapper, :sequel self.strategy = :transaction when :mongo_mapper, :mongoid, :couch_potato, :moped, :ohm, :redis self.strategy = :truncation when :neo4j self.strategy = :transaction end end end end database_cleaner-1.7.0/lib/database_cleaner/configuration.rb000066400000000000000000000057511326617530700241750ustar00rootroot00000000000000require 'database_cleaner/base' module DatabaseCleaner class NoORMDetected < StandardError; end class UnknownStrategySpecified < ArgumentError; end class << self def init_cleaners @cleaners ||= {} # ghetto ordered hash.. maintains 1.8 compat and old API @connections ||= [] end def [](orm,opts = {}) raise NoORMDetected unless orm init_cleaners # TODO: deprecate # this method conflates creation with lookup. Both a command and a query. Yuck. if @cleaners.has_key? [orm, opts] @cleaners[[orm, opts]] else add_cleaner(orm, opts) end end def add_cleaner(orm,opts = {}) init_cleaners cleaner = DatabaseCleaner::Base.new(orm,opts) @cleaners[[orm, opts]] = cleaner @connections << cleaner cleaner end def app_root=(desired_root) @app_root = desired_root end def app_root @app_root ||= Dir.pwd end def connections # double yuck.. can't wait to deprecate this whole class... unless defined?(@cleaners) && @cleaners autodetected = ::DatabaseCleaner::Base.new add_cleaner(autodetected.orm) end @connections end def logger=(log_source) @logger = log_source end def logger return @logger if @logger @logger = Logger.new(STDOUT) @logger.level = Logger::ERROR @logger end def strategy=(stratagem) connections.each { |connect| connect.strategy = stratagem } remove_duplicates end def orm=(orm) connections.each { |connect| connect.orm = orm } remove_duplicates end def start connections.each { |connection| connection.start } end def clean connections.each { |connection| connection.clean } end alias clean! clean def cleaning(&inner_block) connections.inject(inner_block) do |curr_block, connection| proc { connection.cleaning(&curr_block) } end.call end def clean_with(*args) connections.each { |connection| connection.clean_with(*args) } end alias clean_with! clean_with def remove_duplicates temp = [] connections.each do |connect| temp.push connect unless temp.include? connect end @connections = temp end def orm_module(symbol) case symbol when :active_record DatabaseCleaner::ActiveRecord when :data_mapper DatabaseCleaner::DataMapper when :mongo DatabaseCleaner::Mongo when :mongoid DatabaseCleaner::Mongoid when :mongo_mapper DatabaseCleaner::MongoMapper when :moped DatabaseCleaner::Moped when :couch_potato DatabaseCleaner::CouchPotato when :sequel DatabaseCleaner::Sequel when :ohm DatabaseCleaner::Ohm when :redis DatabaseCleaner::Redis when :neo4j DatabaseCleaner::Neo4j end end end end database_cleaner-1.7.0/lib/database_cleaner/couch_potato/000077500000000000000000000000001326617530700234605ustar00rootroot00000000000000database_cleaner-1.7.0/lib/database_cleaner/couch_potato/base.rb000066400000000000000000000001651326617530700247210ustar00rootroot00000000000000module DatabaseCleaner module CouchPotato def self.available_strategies %w[truncation] end end end database_cleaner-1.7.0/lib/database_cleaner/couch_potato/truncation.rb000066400000000000000000000012721326617530700261750ustar00rootroot00000000000000require 'database_cleaner/generic/truncation' module DatabaseCleaner module CouchPotato class Truncation include ::DatabaseCleaner::Generic::Truncation def initialize(options = {}) if options.has_key?(:only) || options.has_key?(:except) raise ArgumentError, "The :only and :except options are not available for use with CouchPotato/CouchDB." elsif !options.empty? raise ArgumentError, "Unsupported option. You specified #{options.keys.join(',')}." end super end def clean database.recreate! end private def database ::CouchPotato.couchrest_database end end end end database_cleaner-1.7.0/lib/database_cleaner/cucumber.rb000066400000000000000000000001031326617530700231150ustar00rootroot00000000000000Around do |scenario, block| DatabaseCleaner.cleaning(&block) end database_cleaner-1.7.0/lib/database_cleaner/data_mapper/000077500000000000000000000000001326617530700232465ustar00rootroot00000000000000database_cleaner-1.7.0/lib/database_cleaner/data_mapper/base.rb000066400000000000000000000005401326617530700245040ustar00rootroot00000000000000require 'database_cleaner/generic/base' module DatabaseCleaner module DataMapper def self.available_strategies %w[truncation transaction] end module Base include ::DatabaseCleaner::Generic::Base def db=(desired_db) @db = desired_db end def db @db ||= :default end end end end database_cleaner-1.7.0/lib/database_cleaner/data_mapper/transaction.rb000066400000000000000000000013641326617530700261240ustar00rootroot00000000000000require 'database_cleaner/data_mapper/base' require 'database_cleaner/generic/transaction' module DatabaseCleaner::DataMapper class Transaction include ::DatabaseCleaner::DataMapper::Base include ::DatabaseCleaner::Generic::Transaction def start(repository = self.db) ::DataMapper.repository(repository) do |r| transaction = DataMapper::Transaction.new(r) transaction.begin r.adapter.push_transaction(transaction) end end def clean(repository = self.db) ::DataMapper.repository(repository) do |r| adapter = r.adapter while adapter.current_transaction adapter.current_transaction.rollback adapter.pop_transaction end end end end end database_cleaner-1.7.0/lib/database_cleaner/data_mapper/truncation.rb000066400000000000000000000116061326617530700257650ustar00rootroot00000000000000require "database_cleaner/generic/truncation" require 'database_cleaner/data_mapper/base' module DataMapper module Adapters class DataObjectsAdapter def storage_names(repository = :default) raise NotImplementedError end def truncate_tables(table_names) table_names.each do |table_name| truncate_table table_name end end end class MysqlAdapter < DataObjectsAdapter # taken from http://github.com/godfat/dm-mapping/tree/master def storage_names(repository = :default) select 'SHOW TABLES' end def truncate_table(table_name) execute("TRUNCATE TABLE #{quote_name(table_name)};") end # copied from activerecord def disable_referential_integrity old = select("SELECT @@FOREIGN_KEY_CHECKS;") begin execute("SET FOREIGN_KEY_CHECKS = 0;") yield ensure execute("SET FOREIGN_KEY_CHECKS = ?", *old) end end end module SqliteAdapterMethods # taken from http://github.com/godfat/dm-mapping/tree/master def storage_names(repository = :default) # activerecord-2.1.0/lib/active_record/connection_adapters/sqlite_adapter.rb: 177 sql = <<-SQL SELECT name FROM sqlite_master WHERE type = 'table' AND NOT name = 'sqlite_sequence' SQL # activerecord-2.1.0/lib/active_record/connection_adapters/sqlite_adapter.rb: 181 select(sql) end def truncate_table(table_name) execute("DELETE FROM #{quote_name(table_name)};") if uses_sequence? execute("DELETE FROM sqlite_sequence where name = '#{table_name}';") end end # this is a no-op copied from activerecord # i didn't find out if/how this is possible # activerecord also doesn't do more here def disable_referential_integrity yield end private # Returns a boolean indicating if the SQLite database is using the sqlite_sequence table. def uses_sequence? sql = <<-SQL SELECT name FROM sqlite_master WHERE type='table' AND name='sqlite_sequence' SQL select(sql).first end end class SqliteAdapter; include SqliteAdapterMethods; end class Sqlite3Adapter; include SqliteAdapterMethods; end # FIXME # i don't know if this works # i basically just copied activerecord code to get a rough idea what they do. # i don't have postgres available, so i won't be the one to write this. # maybe codes below gets some postgres/datamapper user going, though. class PostgresAdapter < DataObjectsAdapter # taken from http://github.com/godfat/dm-mapping/tree/master def storage_names(repository = :default) sql = <<-SQL SELECT table_name FROM "information_schema"."tables" WHERE table_schema = current_schema() and table_type = 'BASE TABLE' SQL select(sql) end def truncate_table(table_name) execute("TRUNCATE TABLE #{quote_name(table_name)} RESTART IDENTITY CASCADE;") end # override to use a single statement def truncate_tables(table_names) quoted_names = table_names.collect { |n| quote_name(n) }.join(', ') execute("TRUNCATE TABLE #{quoted_names} RESTART IDENTITY;") end # FIXME # copied from activerecord def supports_disable_referential_integrity? version = select("SHOW server_version")[0][0].split('.') (version[0].to_i >= 8 && version[1].to_i >= 1) ? true : false rescue return false end # FIXME # copied unchanged from activerecord def disable_referential_integrity(repository = :default) if supports_disable_referential_integrity? then execute(storage_names(repository).collect do |name| "ALTER TABLE #{quote_name(name)} DISABLE TRIGGER ALL" end.join(";")) end yield ensure if supports_disable_referential_integrity? then execute(storage_names(repository).collect do |name| "ALTER TABLE #{quote_name(name)} ENABLE TRIGGER ALL" end.join(";")) end end end end end module DatabaseCleaner module DataMapper class Truncation include ::DatabaseCleaner::DataMapper::Base include ::DatabaseCleaner::Generic::Truncation def clean(repository = self.db) adapter = ::DataMapper.repository(repository).adapter adapter.disable_referential_integrity do adapter.truncate_tables(tables_to_truncate(repository)) end end private def tables_to_truncate(repository = self.db) (@only || ::DataMapper.repository(repository).adapter.storage_names(repository)) - @tables_to_exclude end # overwritten def migration_storage_names %w[migration_info] end end end end database_cleaner-1.7.0/lib/database_cleaner/generic/000077500000000000000000000000001326617530700224055ustar00rootroot00000000000000database_cleaner-1.7.0/lib/database_cleaner/generic/base.rb000066400000000000000000000006401326617530700236440ustar00rootroot00000000000000module ::DatabaseCleaner module Generic module Base def self.included(base) base.extend(ClassMethods) end def db :default end def cleaning(&block) begin start yield ensure clean end end module ClassMethods def available_strategies %W[] end end end end end database_cleaner-1.7.0/lib/database_cleaner/generic/transaction.rb000066400000000000000000000003661326617530700252640ustar00rootroot00000000000000module DatabaseCleaner module Generic module Transaction def initialize(opts = {}) if !opts.empty? raise ArgumentError, "Options are not available for transaction strategies." end end end end end database_cleaner-1.7.0/lib/database_cleaner/generic/truncation.rb000066400000000000000000000024611326617530700251230ustar00rootroot00000000000000module DatabaseCleaner module Generic module Truncation def initialize(opts={}) if !opts.empty? && !(opts.keys - [:only, :except, :pre_count, :reset_ids, :cache_tables]).empty? raise ArgumentError, "The only valid options are :only, :except, :pre_count, :reset_ids or :cache_tables. You specified #{opts.keys.join(',')}." end if opts.has_key?(:only) && opts.has_key?(:except) raise ArgumentError, "You may only specify either :only or :except. Doing both doesn't really make sense does it?" end @only = opts[:only] @tables_to_exclude = Array( (opts[:except] || []).dup ).flatten @tables_to_exclude += migration_storage_names @pre_count = opts[:pre_count] @reset_ids = opts[:reset_ids] @cache_tables = opts.has_key?(:cache_tables) ? !!opts[:cache_tables] : true end def start #included for compatability reasons, do nothing if you don't need to end def clean raise NotImplementedError end private def tables_to_truncate raise NotImplementedError end # overwrite in subclasses # default implementation given because migration storage need not be present def migration_storage_names %w[] end end end end database_cleaner-1.7.0/lib/database_cleaner/mongo/000077500000000000000000000000001326617530700221105ustar00rootroot00000000000000database_cleaner-1.7.0/lib/database_cleaner/mongo/base.rb000066400000000000000000000004561326617530700233540ustar00rootroot00000000000000module DatabaseCleaner module Mongo def self.available_strategies %w[truncation] end module Base def db=(desired_db) @db = desired_db end def db @db || raise("You have not specified a database. (see Mongo::Database)") end end end end database_cleaner-1.7.0/lib/database_cleaner/mongo/truncation.rb000066400000000000000000000033021326617530700246210ustar00rootroot00000000000000require 'database_cleaner/mongo/base' require 'database_cleaner/generic/truncation' require 'database_cleaner/mongo/truncation_mixin' module DatabaseCleaner module Mongo class Truncation include ::DatabaseCleaner::Generic::Truncation include TruncationMixin include Base private def database db end def collections_cache @@collections_cache ||= {} end def mongoid_collection_names @@mongoid_collection_names ||= Hash.new{|h,k| h[k]=[]}.tap do |names| ObjectSpace.each_object(Class) do |klass| (names[klass.db.name] << klass.collection_name) if valid_collection_name?(klass) end end end def not_caching(db_name, list) @@not_caching ||= {} unless @@not_caching.has_key?(db_name) @@not_caching[db_name] = true puts "Not caching collection names for db #{db_name}. Missing these from models: #{list}" end end def collections return collections_cache[database.name] if collections_cache.has_key?(database.name) db_collections = database.collections.select { |c| c.name !~ /^system\./ } missing_collections = mongoid_collection_names[database.name] - db_collections.map(&:name) if missing_collections.empty? collections_cache[database.name] = db_collections else not_caching(database.name, missing_collections) end db_collections end private def valid_collection_name?(klass) klass.ancestors.map(&:to_s).include?('Mongoid::Document') && !klass.embedded && !klass.collection_name.empty? end end end end database_cleaner-1.7.0/lib/database_cleaner/mongo/truncation_mixin.rb000066400000000000000000000011711326617530700260270ustar00rootroot00000000000000module DatabaseCleaner module Mongo module TruncationMixin def clean if @only collections.each { |c| c.send(truncate_method_name) if @only.include?(c.name) } else collections.each { |c| c.send(truncate_method_name) unless @tables_to_exclude.include?(c.name) } end true end private def collections database.collections.select { |c| c.name !~ /^system\./ } end def truncate_method_name # This constant only exists in the 2.x series. defined?(::Mongo::VERSION) ? :delete_many : :remove end end end end database_cleaner-1.7.0/lib/database_cleaner/mongo2/000077500000000000000000000000001326617530700221725ustar00rootroot00000000000000database_cleaner-1.7.0/lib/database_cleaner/mongo2/base.rb000066400000000000000000000004601326617530700234310ustar00rootroot00000000000000module DatabaseCleaner module Mongo2 def self.available_strategies %w[truncation] end module Base def db=(desired_db) @db = desired_db end def db @db || raise("You have not specified a database. (see Mongo2::Database)") end end end end database_cleaner-1.7.0/lib/database_cleaner/mongo2/truncation_mixin.rb000066400000000000000000000016211326617530700261110ustar00rootroot00000000000000module DatabaseCleaner module Mongo2 module TruncationMixin def clean if @only collections.each { |c| database[c].find.delete_many if @only.include?(c) } else collections.each { |c| database[c].find.delete_many unless @tables_to_exclude.include?(c) } end true end private def database if @db.nil? || @db == :default ::Mongoid::Clients.default else ::Mongoid::Clients.with_name(@db) end end def collections if db != :default database.use(db) end database.collections.collect { |c| c.namespace.split('.',2)[1] } # database['system.namespaces'].find(:name => { '$not' => /\.system\.|\$/ }).to_a.map do |collection| # _, name = collection['name'].split('.', 2) # name # end end end end end database_cleaner-1.7.0/lib/database_cleaner/mongo_mapper/000077500000000000000000000000001326617530700234545ustar00rootroot00000000000000database_cleaner-1.7.0/lib/database_cleaner/mongo_mapper/base.rb000066400000000000000000000005241326617530700247140ustar00rootroot00000000000000require 'database_cleaner/generic/base' module DatabaseCleaner module MongoMapper def self.available_strategies %w[truncation] end module Base include ::DatabaseCleaner::Generic::Base def db=(desired_db) @db = desired_db end def db @db ||= :default end end end end database_cleaner-1.7.0/lib/database_cleaner/mongo_mapper/truncation.rb000066400000000000000000000007231326617530700261710ustar00rootroot00000000000000require 'database_cleaner/mongo_mapper/base' require 'database_cleaner/generic/truncation' require 'database_cleaner/mongo/truncation_mixin' module DatabaseCleaner module MongoMapper class Truncation include ::DatabaseCleaner::MongoMapper::Base include ::DatabaseCleaner::Generic::Truncation include ::DatabaseCleaner::Mongo::TruncationMixin private def database ::MongoMapper.database end end end end database_cleaner-1.7.0/lib/database_cleaner/mongoid/000077500000000000000000000000001326617530700224255ustar00rootroot00000000000000database_cleaner-1.7.0/lib/database_cleaner/mongoid/base.rb000066400000000000000000000005171326617530700236670ustar00rootroot00000000000000require 'database_cleaner/generic/base' module DatabaseCleaner module Mongoid def self.available_strategies %w[truncation] end module Base include ::DatabaseCleaner::Generic::Base def db=(desired_db) @db = desired_db end def db @db || :default end end end end database_cleaner-1.7.0/lib/database_cleaner/mongoid/truncation.rb000066400000000000000000000021341326617530700251400ustar00rootroot00000000000000require 'database_cleaner/mongoid/base' require 'database_cleaner/generic/truncation' require 'database_cleaner/mongo/truncation_mixin' require 'database_cleaner/mongo2/truncation_mixin' require 'database_cleaner/moped/truncation_base' require 'mongoid/version' module DatabaseCleaner module Mongoid class Truncation include ::DatabaseCleaner::Mongoid::Base include ::DatabaseCleaner::Generic::Truncation if ::Mongoid::VERSION < '3' include ::DatabaseCleaner::Mongo::TruncationMixin private def database ::Mongoid.database end elsif ::Mongoid::VERSION < '5' include ::DatabaseCleaner::Moped::TruncationBase private def session ::Mongoid::VERSION > "5.0.0" ? ::Mongoid.default_client : ::Mongoid.default_session end def database if not(@db.nil? or @db == :default) ::Mongoid.databases[@db] else ::Mongoid.database end end else include ::DatabaseCleaner::Mongo2::TruncationMixin end end end end database_cleaner-1.7.0/lib/database_cleaner/moped/000077500000000000000000000000001326617530700220755ustar00rootroot00000000000000database_cleaner-1.7.0/lib/database_cleaner/moped/base.rb000066400000000000000000000012341326617530700233340ustar00rootroot00000000000000require 'database_cleaner/generic/base' module DatabaseCleaner module Moped def self.available_strategies %w[truncation] end module Base include ::DatabaseCleaner::Generic::Base def db=(desired_db) @db = desired_db end def db @db ||= :default end def host_port=(desired_host) @host = desired_host end def host @host ||= '127.0.0.1:27017' end def db_version @db_version ||= session.command('buildinfo' => 1)['version'] end private def session ::Moped::Session.new([host], database: db) end end end end database_cleaner-1.7.0/lib/database_cleaner/moped/truncation.rb000066400000000000000000000002661326617530700246140ustar00rootroot00000000000000require 'database_cleaner/moped/truncation_base' module DatabaseCleaner module Moped class Truncation include ::DatabaseCleaner::Moped::TruncationBase end end end database_cleaner-1.7.0/lib/database_cleaner/moped/truncation_base.rb000066400000000000000000000021121326617530700255760ustar00rootroot00000000000000require 'database_cleaner/moped/base' require 'database_cleaner/generic/truncation' module DatabaseCleaner module Moped module TruncationBase include ::DatabaseCleaner::Moped::Base include ::DatabaseCleaner::Generic::Truncation def clean if @only collections.each { |c| session[c].find.remove_all if @only.include?(c) } else collections.each { |c| session[c].find.remove_all unless @tables_to_exclude.include?(c) } end true end private def collections if db != :default session.use(db) end if db_version.split('.').first.to_i >= 3 session.command(listCollections: 1, filter: { 'name' => { '$not' => /.?system\.|\$/ } })['cursor']['firstBatch'].map do |collection| collection['name'] end else session['system.namespaces'].find(name: { '$not' => /\.system\.|\$/ }).to_a.map do |collection| _, name = collection['name'].split('.', 2) name end end end end end end database_cleaner-1.7.0/lib/database_cleaner/neo4j/000077500000000000000000000000001326617530700220105ustar00rootroot00000000000000database_cleaner-1.7.0/lib/database_cleaner/neo4j/base.rb000066400000000000000000000022751326617530700232550ustar00rootroot00000000000000require 'database_cleaner/generic/base' module DatabaseCleaner module Neo4j def self.available_strategies %w[transaction truncation deletion] end module Base include ::DatabaseCleaner::Generic::Base def db=(desired_db) @db = desired_db == :default ? nil : desired_db end def db @db ||= nil end def start if db_type == :embedded_db and not session.running? session.start else session end end def database db && default_db.merge(db) || default_db end private def default_db {:type => default_db_type, :path => default_db_path} end def default_db_type :server_db end def default_db_path(type = default_db_type) type == :server_db ? 'http://localhost:7475/' : './db/test' end def db_type database[:type] end def db_path database[:path] end def db_params database.reject!{|key, value| [:type, :path].include? key } end def session @session ||= ::Neo4j::Session.open(db_type, db_path, db_params) end end end end database_cleaner-1.7.0/lib/database_cleaner/neo4j/deletion.rb000066400000000000000000000005121326617530700241360ustar00rootroot00000000000000require 'database_cleaner/neo4j/base' require 'neo4j-core' module DatabaseCleaner module Neo4j class Deletion include ::DatabaseCleaner::Neo4j::Base def clean ::Neo4j::Transaction.run do session._query('MATCH (n) OPTIONAL MATCH (n)-[r]-() DELETE n,r') end end end end end database_cleaner-1.7.0/lib/database_cleaner/neo4j/transaction.rb000066400000000000000000000011301326617530700246550ustar00rootroot00000000000000require 'database_cleaner/neo4j/base' require 'database_cleaner/generic/transaction' require 'neo4j-core' module DatabaseCleaner module Neo4j class Transaction include ::DatabaseCleaner::Generic::Transaction include ::DatabaseCleaner::Neo4j::Base attr_accessor :tx def start super rollback self.tx = ::Neo4j::Transaction.new end def clean rollback end private def rollback if tx tx.failure tx.close end ensure self.tx = nil end end end end database_cleaner-1.7.0/lib/database_cleaner/neo4j/truncation.rb000066400000000000000000000003011326617530700245150ustar00rootroot00000000000000require 'database_cleaner/neo4j/base' require 'database_cleaner/neo4j/deletion' module DatabaseCleaner module Neo4j class Truncation < DatabaseCleaner::Neo4j::Deletion end end end database_cleaner-1.7.0/lib/database_cleaner/null_strategy.rb000066400000000000000000000004121326617530700242070ustar00rootroot00000000000000module DatabaseCleaner class NullStrategy def self.start # no-op end def self.db=(connection) # no-op end def self.clean # no-op end def self.cleaning(&block) # no-op yield end end end database_cleaner-1.7.0/lib/database_cleaner/ohm/000077500000000000000000000000001326617530700215545ustar00rootroot00000000000000database_cleaner-1.7.0/lib/database_cleaner/ohm/truncation.rb000066400000000000000000000003461326617530700242720ustar00rootroot00000000000000require 'database_cleaner/redis/truncation' module DatabaseCleaner module Ohm class Truncation < ::DatabaseCleaner::Redis::Truncation private def default_redis ::Ohm.redis end end end end database_cleaner-1.7.0/lib/database_cleaner/redis/000077500000000000000000000000001326617530700220775ustar00rootroot00000000000000database_cleaner-1.7.0/lib/database_cleaner/redis/base.rb000066400000000000000000000012031326617530700233320ustar00rootroot00000000000000require 'database_cleaner/generic/base' module DatabaseCleaner module Redis def self.available_strategies %w{truncation} end module Base include ::DatabaseCleaner::Generic::Base def db=(desired_db) @db = desired_db end def db @db ||= :default end alias url db private def connection @connection ||= begin if url == :default ::Redis.new elsif db.is_a?(::Redis) # pass directly the connection db else ::Redis.new(:url => url) end end end end end end database_cleaner-1.7.0/lib/database_cleaner/redis/truncation.rb000066400000000000000000000013501326617530700246110ustar00rootroot00000000000000require 'database_cleaner/redis/base' require 'database_cleaner/generic/truncation' module DatabaseCleaner module Redis class Truncation include ::DatabaseCleaner::Redis::Base include ::DatabaseCleaner::Generic::Truncation def clean if @only @only.each do |term| connection.keys(term).each { |k| connection.del k } end elsif @tables_to_exclude keys_except = [] @tables_to_exclude.each { |term| keys_except += connection.keys(term) } connection.keys.each { |k| connection.del(k) unless keys_except.include?(k) } else connection.flushdb end connection.quit unless url == :default end end end end database_cleaner-1.7.0/lib/database_cleaner/safeguard.rb000066400000000000000000000030731326617530700232620ustar00rootroot00000000000000module DatabaseCleaner class Safeguard class Error < Exception class RemoteDatabaseUrl < Error def initialize super("ENV['DATABASE_URL'] is set to a remote URL. Please refer to https://github.com/DatabaseCleaner/database_cleaner#safeguards") end end class ProductionEnv < Error def initialize(env) super("ENV['#{env}'] is set to production. Please refer to https://github.com/DatabaseCleaner/database_cleaner#safeguards") end end end class RemoteDatabaseUrl LOCAL = %w(localhost 127.0.0.1) def run raise Error::RemoteDatabaseUrl if !skip? && given? end private def given? remote?(ENV['DATABASE_URL']) end def remote?(url) url && !LOCAL.any? { |str| url.include?(str) } end def skip? ENV['DATABASE_CLEANER_ALLOW_REMOTE_DATABASE_URL'] || DatabaseCleaner.allow_remote_database_url end end class Production KEYS = %w(ENV RACK_ENV RAILS_ENV) def run raise Error::ProductionEnv.new(key) if !skip? && given? end private def given? !!key end def key @key ||= KEYS.detect { |key| ENV[key] == 'production' } end def skip? ENV['DATABASE_CLEANER_ALLOW_PRODUCTION'] || DatabaseCleaner.allow_production end end CHECKS = [ RemoteDatabaseUrl, Production ] def run CHECKS.each { |const| const.new.run } end end end database_cleaner-1.7.0/lib/database_cleaner/sequel/000077500000000000000000000000001326617530700222675ustar00rootroot00000000000000database_cleaner-1.7.0/lib/database_cleaner/sequel/base.rb000066400000000000000000000010651326617530700235300ustar00rootroot00000000000000require 'database_cleaner/generic/base' module DatabaseCleaner module Sequel def self.available_strategies %w(truncation transaction deletion) end module Base include ::DatabaseCleaner::Generic::Base def db=(desired_db) @db = desired_db end def db return @db if @db && @db != :default raise "As you have more than one active sequel database you have to specify the one to use manually!" if ::Sequel::DATABASES.count > 1 ::Sequel::DATABASES.first || :default end end end end database_cleaner-1.7.0/lib/database_cleaner/sequel/deletion.rb000066400000000000000000000023071326617530700244210ustar00rootroot00000000000000require 'database_cleaner/sequel/base' require 'database_cleaner/generic/truncation' require 'database_cleaner/sequel/truncation' module DatabaseCleaner::Sequel class Deletion < Truncation def disable_referential_integrity(tables) case db.database_type when :postgres db.run('SET CONSTRAINTS ALL DEFERRED') tables_to_truncate(db).each do |table| db.run("ALTER TABLE \"#{table}\" DISABLE TRIGGER ALL") end when :mysql old = db.fetch('SELECT @@FOREIGN_KEY_CHECKS').first[:@@FOREIGN_KEY_CHECKS] db.run('SET FOREIGN_KEY_CHECKS = 0') end yield ensure case db.database_type when :postgres tables.each do |table| db.run("ALTER TABLE \"#{table}\" ENABLE TRIGGER ALL") end when :mysql db.run("SET FOREIGN_KEY_CHECKS = #{old}") end end def delete_tables(db, tables) tables.each do |table| db[table.to_sym].delete end end def clean return unless dirty? tables = tables_to_truncate(db) db.transaction do disable_referential_integrity(tables) do delete_tables(db, tables) end end end end end database_cleaner-1.7.0/lib/database_cleaner/sequel/transaction.rb000066400000000000000000000021231326617530700251370ustar00rootroot00000000000000require 'database_cleaner/sequel/base' module DatabaseCleaner module Sequel class Transaction include ::DatabaseCleaner::Sequel::Base def self.check_fiber_brokenness if !@checked_fiber_brokenness && Fiber.new { Thread.current }.resume != Thread.current raise RuntimeError, "This ruby engine's Fibers are not compatible with Sequel's connection pool. " + "To work around this, please use DatabaseCleaner.cleaning with a block instead of " + "DatabaseCleaner.start and DatabaseCleaner.clean" end @checked_fiber_brokenness = true end def start self.class.check_fiber_brokenness @fibers ||= [] db = self.db f = Fiber.new do db.transaction(:rollback => :always, :savepoint => true) do Fiber.yield end end f.resume @fibers << f end def clean f = @fibers.pop f.resume end def cleaning self.db.transaction(:rollback => :always, :savepoint => true) { yield } end end end end database_cleaner-1.7.0/lib/database_cleaner/sequel/truncation.rb000066400000000000000000000040031326617530700247770ustar00rootroot00000000000000require 'database_cleaner/generic/truncation' require 'database_cleaner/sequel/base' module DatabaseCleaner module Sequel class Truncation include ::DatabaseCleaner::Sequel::Base include ::DatabaseCleaner::Generic::Truncation def start @last_txid = txid end def clean return unless dirty? case db.database_type when :postgres # PostgreSQL requires all tables with FKs to be truncates in the same command, or have the CASCADE keyword # appended. Bulk truncation without CASCADE is: # * Safer. Tables outside of tables_to_truncate won't be affected. # * Faster. Less roundtrips to the db. unless (tables = tables_to_truncate(db)).empty? all_tables = tables.map { |t| %("#{t}") }.join(',') db.run "TRUNCATE TABLE #{all_tables};" end else tables = tables_to_truncate(db) if pre_count? # Count rows before truncating pre_count_truncate_tables(db, tables) else # Truncate each table normally truncate_tables(db, tables) end end end private def pre_count_truncate_tables(db, tables) tables = tables.reject { |table| db[table.to_sym].count == 0 } truncate_tables(db, tables) end def truncate_tables(db, tables) tables.each do |table| db[table.to_sym].truncate end end def dirty? @last_txid != txid || @last_txid.nil? end def txid case db.database_type when :postgres db.fetch('SELECT txid_snapshot_xmax(txid_current_snapshot()) AS txid').first[:txid] end end def tables_to_truncate(db) (@only || db.tables.map(&:to_s)) - @tables_to_exclude end # overwritten def migration_storage_names %w(schema_info schema_migrations) end def pre_count? @pre_count == true end end end end database_cleaner-1.7.0/spec/000077500000000000000000000000001326617530700157205ustar00rootroot00000000000000database_cleaner-1.7.0/spec/database_cleaner/000077500000000000000000000000001326617530700211555ustar00rootroot00000000000000database_cleaner-1.7.0/spec/database_cleaner/active_record/000077500000000000000000000000001326617530700237665ustar00rootroot00000000000000database_cleaner-1.7.0/spec/database_cleaner/active_record/base_spec.rb000066400000000000000000000134071326617530700262440ustar00rootroot00000000000000require 'spec_helper' require 'active_record' require 'database_cleaner/active_record/base' require 'database_cleaner/shared_strategy' class FakeModel def self.connection :fake_connection end end module DatabaseCleaner describe ActiveRecord do it { should respond_to(:available_strategies) } describe "config_file_location" do subject { ActiveRecord.config_file_location } it "should default to DatabaseCleaner.root / config / database.yml" do ActiveRecord.config_file_location=nil DatabaseCleaner.should_receive(:app_root).and_return("/path/to") subject.should eq '/path/to/config/database.yml' end end end module ActiveRecord class ExampleStrategy include ::DatabaseCleaner::ActiveRecord::Base end describe ExampleStrategy do let :config_location do '/path/to/config/database.yml' end before { ::DatabaseCleaner::ActiveRecord.stub(:config_file_location).and_return(config_location) } it_should_behave_like "a generic strategy" describe "db" do it "should store my desired db" do subject.stub(:load_config) subject.db = :my_db subject.db.should eq :my_db end it "should default to :default" do subject.db.should eq :default end it "should load_config when I set db" do subject.should_receive(:load_config) subject.db = :my_db end end describe "load_config" do before do subject.db = :my_db yaml = <<-Y my_db: database: <%= "ONE".downcase %> Y File.stub(:file?).with(config_location).and_return(true) IO.stub(:read).with(config_location).and_return(yaml) end it "should parse the config" do YAML.should_receive(:load).and_return({ :nil => nil }) subject.load_config end it "should process erb in the config" do transformed = <<-Y my_db: database: one Y YAML.should_receive(:load).with(transformed).and_return({ "my_db" => { "database" => "one" } }) subject.load_config end context 'use ActiveRecord::Base.configuration' do it 'when config file different with it' do ::ActiveRecord::Base.stub(:configurations).and_return({ "my_db" =>{ "database" => "two"} }) subject.load_config subject.connection_hash.should eq({ "database" => "two"}) end end context 'use config file' do it 'when config file same with it' do ::ActiveRecord::Base.stub(:configurations).and_return({ "my_db" =>{ "database" => "one"} }) subject.load_config subject.connection_hash.should eq({ "database" => "one"}) end it 'when ::ActiveRecord::Base.configurations nil' do ::ActiveRecord::Base.stub(:configurations).and_return(nil) subject.load_config subject.connection_hash.should eq({ "database" => "one"}) end it 'when ::ActiveRecord::Base.configurations empty' do ::ActiveRecord::Base.stub(:configurations).and_return({}) subject.load_config subject.connection_hash.should eq({ "database" => "one"}) end end it "should store the relevant config in connection_hash" do subject.load_config subject.connection_hash.should eq( "database" => "one" ) end it "should skip config if config file is not available" do File.should_receive(:file?).with(config_location).and_return(false) subject.load_config subject.connection_hash.should_not be end it "skips the file when the model is set" do subject.db = FakeModel YAML.should_not_receive(:load) subject.load_config subject.connection_hash.should_not be end it "skips the file when the db is set to :default" do # to avoid https://github.com/bmabey/database_cleaner/issues/72 subject.db = :default YAML.should_not_receive(:load) subject.load_config subject.connection_hash.should_not be end end describe "connection_hash" do it "should store connection_hash" do subject.connection_hash = { :key => "value" } subject.connection_hash.should eq( :key => "value" ) end end describe "connection_class" do it { expect { subject.connection_class }.to_not raise_error } it "should default to ActiveRecord::Base" do subject.connection_class.should eq ::ActiveRecord::Base end context "with database models" do context "connection_hash is set" do it "allows for database models to be passed in" do subject.db = FakeModel subject.connection_hash = { } subject.load_config subject.connection_class.should eq FakeModel end end context "connection_hash is not set" do it "allows for database models to be passed in" do subject.db = FakeModel subject.connection_class.should eq FakeModel end end end context "when connection_hash is set" do let(:hash) { double("hash") } before { ::ActiveRecord::Base.stub(:respond_to?).and_return(false) } before { subject.stub(:connection_hash).and_return(hash) } it "establish a connection using ActiveRecord::Base" do ::ActiveRecord::Base.should_receive(:establish_connection).with(hash) expect(subject.connection_class).to eq ::ActiveRecord::Base end end end end end end database_cleaner-1.7.0/spec/database_cleaner/active_record/transaction_spec.rb000066400000000000000000000175051326617530700276620ustar00rootroot00000000000000require File.dirname(__FILE__) + '/../../spec_helper' require 'database_cleaner/active_record/transaction' require 'active_record' module DatabaseCleaner module ActiveRecord describe Transaction do let (:connection) { double("connection") } let (:connection_2) { double("connection") } let (:connection_pool) { double("connection_pool")} before(:each) do ::ActiveRecord::Base.stub(:connection_pool).and_return(connection_pool) connection_pool.stub(:connections).and_return([connection]) ::ActiveRecord::Base.stub(:connection).and_return(connection) end describe "#start" do [:begin_transaction, :begin_db_transaction].each do |begin_transaction_method| context "using #{begin_transaction_method}" do before do connection.stub(:transaction) connection.stub(begin_transaction_method) connection.stub(:respond_to?).with(:begin_transaction).and_return(:begin_transaction == begin_transaction_method) end it "should increment open transactions if possible" do connection.stub(:respond_to?).with(:increment_open_transactions).and_return(true) connection.should_receive(:increment_open_transactions) Transaction.new.start end it "should tell ActiveRecord to increment connection if its not possible to increment current connection" do connection.stub(:respond_to?).with(:increment_open_transactions).and_return(false) ::ActiveRecord::Base.should_receive(:increment_open_transactions) Transaction.new.start end it "should start a transaction" do connection.stub(:respond_to?).with(:increment_open_transactions).and_return(true) connection.stub(:increment_open_transactions) connection.should_receive(begin_transaction_method) connection.should_receive(:transaction) Transaction.new.start end end end end describe "#clean" do context "manual accounting of transaction count" do it "should start a transaction" do connection.should_receive(:open_transactions).and_return(1) connection.stub(:decrement_open_transactions) connection.should_receive(:rollback_db_transaction) Transaction.new.clean end it "should decrement open transactions if possible" do connection.should_receive(:open_transactions).and_return(1) connection.stub(:respond_to?).with(:decrement_open_transactions).and_return(true) connection.stub(:respond_to?).with(:rollback_transaction_records, true).and_return(false) connection.stub(:respond_to?).with(:rollback_transaction).and_return(false) connection.stub(:rollback_db_transaction) connection.should_receive(:decrement_open_transactions) Transaction.new.clean end it "should not try to decrement or rollback if open_transactions is 0 for whatever reason" do connection.should_receive(:open_transactions).and_return(0) Transaction.new.clean end it "should decrement connection via ActiveRecord::Base if connection won't" do connection.should_receive(:open_transactions).and_return(1) connection.stub(:respond_to?).with(:decrement_open_transactions).and_return(false) connection.stub(:respond_to?).with(:rollback_transaction_records, true).and_return(false) connection.stub(:respond_to?).with(:rollback_transaction).and_return(false) connection.stub(:rollback_db_transaction) ::ActiveRecord::Base.should_receive(:decrement_open_transactions) Transaction.new.clean end it "should rollback open transactions in all connections" do connection_pool.stub(:connections).and_return([connection, connection_2]) connection.should_receive(:open_transactions).and_return(1) connection.stub(:respond_to?).with(:decrement_open_transactions).and_return(false) connection.stub(:respond_to?).with(:rollback_transaction_records, true).and_return(false) connection.stub(:respond_to?).with(:rollback_transaction).and_return(false) connection.stub(:rollback_db_transaction) connection_2.should_receive(:open_transactions).and_return(1) connection_2.stub(:respond_to?).with(:decrement_open_transactions).and_return(false) connection_2.stub(:respond_to?).with(:rollback_transaction_records, true).and_return(false) connection_2.stub(:respond_to?).with(:rollback_transaction).and_return(false) connection_2.stub(:rollback_db_transaction) ::ActiveRecord::Base.should_receive(:decrement_open_transactions).twice Transaction.new.clean end it "should rollback open transactions in all connections with an open transaction" do connection_pool.stub(:connections).and_return([connection, connection_2]) connection.should_receive(:open_transactions).and_return(1) connection.stub(:respond_to?).with(:decrement_open_transactions).and_return(false) connection.stub(:respond_to?).with(:rollback_transaction_records, true).and_return(false) connection.stub(:respond_to?).with(:rollback_transaction).and_return(false) connection.stub(:rollback_db_transaction) connection_2.should_receive(:open_transactions).and_return(0) ::ActiveRecord::Base.should_receive(:decrement_open_transactions).exactly(1).times Transaction.new.clean end end context "automatic accounting of transaction count (AR 4)" do before {stub_const("ActiveRecord::VERSION::MAJOR", 4) } it "should start a transaction" do connection.stub(:rollback_db_transaction) connection.should_receive(:open_transactions).and_return(1) connection.should_not_receive(:decrement_open_transactions) connection.should_receive(:rollback_transaction) Transaction.new.clean end it "should decrement open transactions if possible" do connection.stub(:rollback_transaction) connection.should_receive(:open_transactions).and_return(1) connection.should_not_receive(:decrement_open_transactions) Transaction.new.clean end it "should not try to decrement or rollback if open_transactions is 0 for whatever reason" do connection.should_receive(:open_transactions).and_return(0) Transaction.new.clean end it "should decrement connection via ActiveRecord::Base if connection won't" do connection.should_receive(:open_transactions).and_return(1) connection.stub(:respond_to?).with(:rollback_transaction_records, true).and_return(false) connection.stub(:respond_to?).with(:rollback_transaction).and_return(true) connection.stub(:rollback_transaction) ::ActiveRecord::Base.should_not_receive(:decrement_open_transactions) Transaction.new.clean end end end describe "#connection_maintains_transaction_count?" do it "should return true if the major active record version is < 4" do stub_const("ActiveRecord::VERSION::MAJOR", 3) Transaction.new.connection_maintains_transaction_count?.should be_true end it "should return false if the major active record version is > 3" do stub_const("ActiveRecord::VERSION::MAJOR", 4) Transaction.new.connection_maintains_transaction_count?.should be_false end end end end end database_cleaner-1.7.0/spec/database_cleaner/active_record/truncation/000077500000000000000000000000001326617530700261545ustar00rootroot00000000000000database_cleaner-1.7.0/spec/database_cleaner/active_record/truncation/mysql2_spec.rb000066400000000000000000000017221326617530700307440ustar00rootroot00000000000000require 'spec_helper' require 'active_record' require 'support/active_record/mysql2_setup' require 'database_cleaner/active_record/truncation' require 'database_cleaner/active_record/truncation/shared_fast_truncation' module ActiveRecord module ConnectionAdapters describe do before(:all) { active_record_mysql2_setup } let(:connection) { active_record_mysql2_connection } describe "#truncate_table" do it "should truncate the table" do 2.times { User.create } connection.truncate_table('users') User.count.should eq 0 end it "should reset AUTO_INCREMENT index of table" do 2.times { User.create } User.delete_all connection.truncate_table('users') User.create.id.should eq 1 end end it_behaves_like "an adapter with pre-count truncation" do let(:connection) { active_record_mysql2_connection } end end end end database_cleaner-1.7.0/spec/database_cleaner/active_record/truncation/mysql_spec.rb000066400000000000000000000017161326617530700306650ustar00rootroot00000000000000require 'spec_helper' require 'active_record' require 'support/active_record/mysql_setup' require 'database_cleaner/active_record/truncation' require 'database_cleaner/active_record/truncation/shared_fast_truncation' module ActiveRecord module ConnectionAdapters describe do before(:all) { active_record_mysql_setup } let(:connection) { active_record_mysql_connection } describe "#truncate_table" do it "should truncate the table" do 2.times { User.create } connection.truncate_table('users') User.count.should eq 0 end it "should reset AUTO_INCREMENT index of table" do 2.times { User.create } User.delete_all connection.truncate_table('users') User.create.id.should eq 1 end end it_behaves_like "an adapter with pre-count truncation" do let(:connection) { active_record_mysql_connection } end end end end database_cleaner-1.7.0/spec/database_cleaner/active_record/truncation/postgresql_spec.rb000066400000000000000000000040671326617530700317250ustar00rootroot00000000000000require 'spec_helper' require 'active_record' require 'support/active_record/postgresql_setup' require 'database_cleaner/active_record/truncation' require 'database_cleaner/active_record/truncation/shared_fast_truncation' module ActiveRecord module ConnectionAdapters describe "schema_migrations table" do it "is not truncated" do active_record_pg_migrate DatabaseCleaner::ActiveRecord::Truncation.new.clean result = active_record_pg_connection.execute("select count(*) from schema_migrations;") result.values.first.should eq ["2"] end end describe do before(:all) { active_record_pg_setup } let(:connection) do active_record_pg_connection end before(:each) do connection.truncate_tables connection.tables end describe "#truncate_table" do it "truncates the table" do 2.times { User.create } connection.truncate_table('users') User.count.should eq 0 end it "truncates the table without id sequence" do 2.times { Agent.create } connection.truncate_table('agents') Agent.count.should eq 0 end it "resets AUTO_INCREMENT index of table" do 2.times { User.create } User.delete_all connection.truncate_table('users') User.create.id.should eq 1 end end describe ":except option cleanup" do it "should not truncate the tables specified in the :except option" do 2.times { User.create } ::DatabaseCleaner::ActiveRecord::Truncation.new(:except => ['users']).clean expect( User.count ).to eq 2 end end describe '#database_cleaner_table_cache' do it 'should default to the list of tables with their schema' do connection.database_cleaner_table_cache.first.should match(/^public\./) end end it_behaves_like "an adapter with pre-count truncation" do let(:connection) { active_record_pg_connection } end end end end database_cleaner-1.7.0/spec/database_cleaner/active_record/truncation/shared_fast_truncation.rb000066400000000000000000000020671326617530700332370ustar00rootroot00000000000000shared_examples_for "an adapter with pre-count truncation" do describe "#pre_count_truncate_tables" do context "with :reset_ids set true" do it "truncates the table" do 2.times { User.create } connection.pre_count_truncate_tables(%w[users], :reset_ids => true) User.count.should be_zero end it "resets AUTO_INCREMENT index of table" do 2.times { User.create } User.delete_all connection.pre_count_truncate_tables(%w[users]) # true is also the default User.create.id.should eq 1 end end context "with :reset_ids set false" do it "truncates the table" do 2.times { User.create } connection.pre_count_truncate_tables(%w[users], :reset_ids => false) User.count.should be_zero end it "does not reset AUTO_INCREMENT index of table" do 2.times { User.create } User.delete_all connection.pre_count_truncate_tables(%w[users], :reset_ids => false) User.create.id.should eq 3 end end end end database_cleaner-1.7.0/spec/database_cleaner/active_record/truncation/sqlite3_spec.rb000066400000000000000000000015371326617530700311050ustar00rootroot00000000000000require 'spec_helper' require 'active_record' require 'support/active_record/sqlite3_setup' require 'database_cleaner/active_record/truncation' module ActiveRecord module ConnectionAdapters describe do before(:all) { active_record_sqlite3_setup } let(:connection) do active_record_sqlite3_connection end before(:each) do connection.truncate_tables connection.tables end describe "#truncate_table" do it "truncates the table" do 2.times { User.create } connection.truncate_table('users') User.count.should eq 0 end it "resets AUTO_INCREMENT index of table" do 2.times { User.create } User.delete_all connection.truncate_table('users') User.create.id.should eq 1 end end end end end database_cleaner-1.7.0/spec/database_cleaner/active_record/truncation_spec.rb000066400000000000000000000152301326617530700275140ustar00rootroot00000000000000require File.dirname(__FILE__) + '/../../spec_helper' require 'active_record' require 'active_record/connection_adapters/mysql_adapter' require 'active_record/connection_adapters/mysql2_adapter' require 'active_record/connection_adapters/sqlite3_adapter' require 'active_record/connection_adapters/postgresql_adapter' require 'database_cleaner/active_record/truncation' module ActiveRecord module ConnectionAdapters #JdbcAdapter IBM_DBAdapter [ MysqlAdapter, Mysql2Adapter, SQLite3Adapter, PostgreSQLAdapter ].each do |adapter| describe adapter, "#truncate_table" do it "responds" do adapter.instance_methods.should include(:truncate_table) end end end end end module DatabaseCleaner module ActiveRecord describe Truncation do let(:connection) { double('connection') } before(:each) do connection.stub(:disable_referential_integrity).and_yield connection.stub(:database_cleaner_view_cache).and_return([]) ::ActiveRecord::Base.stub(:connection).and_return(connection) end describe '#clean' do it "should truncate all tables except for schema_migrations" do connection.stub(:database_cleaner_table_cache).and_return(%w[schema_migrations widgets dogs]) connection.should_receive(:truncate_tables).with(['widgets', 'dogs']) Truncation.new.clean end it "should use ActiveRecord's SchemaMigration.table_name" do connection.stub(:database_cleaner_table_cache).and_return(%w[pre_schema_migrations_suf widgets dogs]) ::ActiveRecord::Base.stub(:table_name_prefix).and_return('pre_') ::ActiveRecord::Base.stub(:table_name_suffix).and_return('_suf') connection.should_receive(:truncate_tables).with(['widgets', 'dogs']) Truncation.new.clean end it "should only truncate the tables specified in the :only option when provided" do connection.stub(:database_cleaner_table_cache).and_return(%w[schema_migrations widgets dogs]) connection.should_receive(:truncate_tables).with(['widgets']) Truncation.new(:only => ['widgets']).clean end it "should not truncate the tables specified in the :except option" do connection.stub(:database_cleaner_table_cache).and_return(%w[schema_migrations widgets dogs]) connection.should_receive(:truncate_tables).with(['dogs']) Truncation.new(:except => ['widgets']).clean end it "should raise an error when :only and :except options are used" do running { Truncation.new(:except => ['widgets'], :only => ['widgets']) }.should raise_error(ArgumentError) end it "should raise an error when invalid options are provided" do running { Truncation.new(:foo => 'bar') }.should raise_error(ArgumentError) end it "should not truncate views" do connection.stub(:database_cleaner_table_cache).and_return(%w[widgets dogs]) connection.stub(:database_cleaner_view_cache).and_return(["widgets"]) connection.should_receive(:truncate_tables).with(['dogs']) Truncation.new.clean end describe "relying on #pre_count_truncate_tables if connection allows it" do subject { Truncation.new } it "should rely on #pre_count_truncate_tables if #pre_count? returns true" do connection.stub(:database_cleaner_table_cache).and_return(%w[widgets dogs]) connection.stub(:database_cleaner_view_cache).and_return(["widgets"]) subject.instance_variable_set(:"@pre_count", true) connection.should_not_receive(:truncate_tables).with(['dogs']) connection.should_receive(:pre_count_truncate_tables).with(['dogs'], :reset_ids => true) subject.clean end it "should not rely on #pre_count_truncate_tables if #pre_count? return false" do connection.stub(:database_cleaner_table_cache).and_return(%w[widgets dogs]) connection.stub(:database_cleaner_view_cache).and_return(["widgets"]) subject.instance_variable_set(:"@pre_count", false) connection.should_not_receive(:pre_count_truncate_tables).with(['dogs'], :reset_ids => true) connection.should_receive(:truncate_tables).with(['dogs']) subject.clean end end context 'when :cache_tables is set to true' do it 'caches the list of tables to be truncated' do connection.should_receive(:database_cleaner_table_cache).and_return([]) connection.should_not_receive(:tables) connection.stub(:truncate_tables) Truncation.new({ :cache_tables => true }).clean end end context 'when :cache_tables is set to false' do it 'does not cache the list of tables to be truncated' do connection.should_not_receive(:database_cleaner_table_cache) connection.should_receive(:tables).and_return([]) connection.stub(:truncate_tables) Truncation.new({ :cache_tables => false }).clean end end end describe '#pre_count?' do before(:each) do connection.stub(:disable_referential_integrity).and_yield connection.stub(:database_cleaner_view_cache).and_return([]) ::ActiveRecord::Base.stub(:connection).and_return(connection) end subject { Truncation.new } its(:pre_count?) { should eq false } it 'should return true if @reset_id is set and non false or nil' do subject.instance_variable_set(:"@pre_count", true) subject.send(:pre_count?).should eq true end it 'should return false if @reset_id is set to false' do subject.instance_variable_set(:"@pre_count", false) subject.send(:pre_count?).should eq false end end describe '#reset_ids?' do before(:each) do connection.stub(:disable_referential_integrity).and_yield connection.stub(:database_cleaner_view_cache).and_return([]) ::ActiveRecord::Base.stub(:connection).and_return(connection) end subject { Truncation.new } its(:reset_ids?) { should eq true } it 'should return true if @reset_id is set and non false or nil' do subject.instance_variable_set(:"@reset_ids", 'Something') subject.send(:reset_ids?).should eq true end it 'should return false if @reset_id is set to false' do subject.instance_variable_set(:"@reset_ids", false) subject.send(:reset_ids?).should eq false end end end end end database_cleaner-1.7.0/spec/database_cleaner/base_spec.rb000066400000000000000000000532411326617530700234330ustar00rootroot00000000000000require File.dirname(__FILE__) + '/../spec_helper' require 'database_cleaner/active_record/transaction' require 'database_cleaner/data_mapper/transaction' require 'database_cleaner/mongo_mapper/truncation' require 'database_cleaner/mongoid/truncation' require 'database_cleaner/couch_potato/truncation' require 'database_cleaner/neo4j/transaction' module DatabaseCleaner describe Base do let(:mock_strategy) { double("strategy").tap{|strategy| strategy.stub(:to_ary => [strategy]) } } describe "autodetect" do #Cache all ORMs, we'll need them later but not now. before(:all) do Temp_AR = ::ActiveRecord if defined?(::ActiveRecord) and not defined?(Temp_AR) Temp_DM = ::DataMapper if defined?(::DataMapper) and not defined?(Temp_DM) Temp_MM = ::MongoMapper if defined?(::MongoMapper) and not defined?(Temp_MM) Temp_MO = ::Mongoid if defined?(::Mongoid) and not defined?(Temp_MO) Temp_CP = ::CouchPotato if defined?(::CouchPotato) and not defined?(Temp_CP) Temp_SQ = ::Sequel if defined?(::Sequel) and not defined?(Temp_SQ) Temp_MP = ::Moped if defined?(::Moped) and not defined?(Temp_MP) Temp_RS = ::Redis if defined?(::Redis) and not defined?(Temp_RS) Temp_OH = ::Ohm if defined?(::Ohm) and not defined?(Temp_OH) Temp_NJ = ::Neo4j if defined?(::Neo4j) and not defined?(Temp_NJ) end #Remove all ORM mocks and restore from cache after(:all) do Object.send(:remove_const, 'ActiveRecord') if defined?(::ActiveRecord) Object.send(:remove_const, 'DataMapper') if defined?(::DataMapper) Object.send(:remove_const, 'MongoMapper') if defined?(::MongoMapper) Object.send(:remove_const, 'Mongoid') if defined?(::Mongoid) Object.send(:remove_const, 'CouchPotato') if defined?(::CouchPotato) Object.send(:remove_const, 'Sequel') if defined?(::Sequel) Object.send(:remove_const, 'Moped') if defined?(::Moped) Object.send(:remove_const, 'Ohm') if defined?(::Ohm) Object.send(:remove_const, 'Redis') if defined?(::Redis) Object.send(:remove_const, 'Neo4j') if defined?(::Neo4j) # Restore ORMs ::ActiveRecord = Temp_AR if defined? Temp_AR ::DataMapper = Temp_DM if defined? Temp_DM ::MongoMapper = Temp_MM if defined? Temp_MM ::Mongoid = Temp_MO if defined? Temp_MO ::CouchPotato = Temp_CP if defined? Temp_CP ::Sequel = Temp_SQ if defined? Temp_SQ ::Moped = Temp_MP if defined? Temp_MP ::Ohm = Temp_OH if defined? Temp_OH ::Redis = Temp_RS if defined? Temp_RS ::Neo4j = Temp_NJ if defined? Temp_NJ end #reset the orm mocks before(:each) do Object.send(:remove_const, 'ActiveRecord') if defined?(::ActiveRecord) Object.send(:remove_const, 'DataMapper') if defined?(::DataMapper) Object.send(:remove_const, 'MongoMapper') if defined?(::MongoMapper) Object.send(:remove_const, 'Mongoid') if defined?(::Mongoid) Object.send(:remove_const, 'CouchPotato') if defined?(::CouchPotato) Object.send(:remove_const, 'Sequel') if defined?(::Sequel) Object.send(:remove_const, 'Moped') if defined?(::Moped) Object.send(:remove_const, 'Ohm') if defined?(::Ohm) Object.send(:remove_const, 'Redis') if defined?(::Redis) Object.send(:remove_const, 'Neo4j') if defined?(::Neo4j) end let(:cleaner) { DatabaseCleaner::Base.new :autodetect } it "should raise an error when no ORM is detected" do running { cleaner }.should raise_error(DatabaseCleaner::NoORMDetected) end it "should detect ActiveRecord first" do Object.const_set('ActiveRecord','Actively mocking records.') Object.const_set('DataMapper', 'Mapping data mocks') Object.const_set('MongoMapper', 'Mapping mock mongos') Object.const_set('Mongoid', 'Mongoid mock') Object.const_set('CouchPotato', 'Couching mock potatos') Object.const_set('Sequel', 'Sequel mock') Object.const_set('Moped', 'Moped mock') Object.const_set('Ohm', 'Ohm mock') Object.const_set('Redis', 'Redis mock') Object.const_set('Neo4j', 'Neo4j mock') cleaner.orm.should eq :active_record cleaner.should be_auto_detected end it "should detect DataMapper second" do Object.const_set('DataMapper', 'Mapping data mocks') Object.const_set('MongoMapper', 'Mapping mock mongos') Object.const_set('Mongoid', 'Mongoid mock') Object.const_set('CouchPotato', 'Couching mock potatos') Object.const_set('Sequel', 'Sequel mock') Object.const_set('Moped', 'Moped mock') Object.const_set('Ohm', 'Ohm mock') Object.const_set('Redis', 'Redis mock') Object.const_set('Neo4j', 'Neo4j mock') cleaner.orm.should eq :data_mapper cleaner.should be_auto_detected end it "should detect MongoMapper third" do Object.const_set('MongoMapper', 'Mapping mock mongos') Object.const_set('Mongoid', 'Mongoid mock') Object.const_set('CouchPotato', 'Couching mock potatos') Object.const_set('Sequel', 'Sequel mock') Object.const_set('Moped', 'Moped mock') Object.const_set('Ohm', 'Ohm mock') Object.const_set('Redis', 'Redis mock') Object.const_set('Neo4j', 'Neo4j mock') cleaner.orm.should eq :mongo_mapper cleaner.should be_auto_detected end it "should detect Mongoid fourth" do Object.const_set('Mongoid', 'Mongoid mock') Object.const_set('CouchPotato', 'Couching mock potatos') Object.const_set('Sequel', 'Sequel mock') Object.const_set('Moped', 'Moped mock') Object.const_set('Ohm', 'Ohm mock') Object.const_set('Redis', 'Redis mock') Object.const_set('Neo4j', 'Neo4j mock') cleaner.orm.should eq :mongoid cleaner.should be_auto_detected end it "should detect CouchPotato fifth" do Object.const_set('CouchPotato', 'Couching mock potatos') Object.const_set('Sequel', 'Sequel mock') Object.const_set('Moped', 'Moped mock') Object.const_set('Ohm', 'Ohm mock') Object.const_set('Redis', 'Redis mock') Object.const_set('Neo4j', 'Neo4j mock') cleaner.orm.should eq :couch_potato cleaner.should be_auto_detected end it "should detect Sequel sixth" do Object.const_set('Sequel', 'Sequel mock') Object.const_set('Moped', 'Moped mock') Object.const_set('Ohm', 'Ohm mock') Object.const_set('Redis', 'Redis mock') Object.const_set('Neo4j', 'Neo4j mock') cleaner.orm.should eq :sequel cleaner.should be_auto_detected end it 'detects Moped seventh' do Object.const_set('Moped', 'Moped mock') cleaner.orm.should eq :moped cleaner.should be_auto_detected end it 'detects Ohm eighth' do Object.const_set('Ohm', 'Ohm mock') Object.const_set('Redis', 'Redis mock') Object.const_set('Neo4j', 'Neo4j mock') cleaner.orm.should eq :ohm cleaner.should be_auto_detected end it 'detects Redis ninth' do Object.const_set('Redis', 'Redis mock') Object.const_set('Neo4j', 'Neo4j mock') cleaner.orm.should eq :redis cleaner.should be_auto_detected end it 'detects Neo4j tenth' do Object.const_set('Neo4j', 'Neo4j mock') cleaner.orm.should eq :neo4j cleaner.should be_auto_detected end end describe "orm_module" do it "should ask ::DatabaseCleaner what the module is for its orm" do orm = double("orm") mockule = double("module") cleaner = ::DatabaseCleaner::Base.new cleaner.should_receive(:orm).and_return(orm) ::DatabaseCleaner.should_receive(:orm_module).with(orm).and_return(mockule) cleaner.send(:orm_module).should eq mockule end end describe "comparison" do it "should be equal if orm, connection and strategy are the same" do one = DatabaseCleaner::Base.new(:active_record,:connection => :default) one.strategy = mock_strategy two = DatabaseCleaner::Base.new(:active_record,:connection => :default) two.strategy = mock_strategy one.should eq two two.should eq one end it "should not be equal if orm are not the same" do one = DatabaseCleaner::Base.new(:mongo_id, :connection => :default) one.strategy = mock_strategy two = DatabaseCleaner::Base.new(:active_record, :connection => :default) two.strategy = mock_strategy one.should_not eq two two.should_not eq one end it "should not be equal if connection are not the same" do one = DatabaseCleaner::Base.new(:active_record, :connection => :default) one.strategy = :truncation two = DatabaseCleaner::Base.new(:active_record, :connection => :other) two.strategy = :truncation one.should_not eq two two.should_not eq one end end describe "initialization" do context "db specified" do subject { ::DatabaseCleaner::Base.new(:active_record,:connection => :my_db) } it "should store db from :connection in params hash" do subject.db.should eq :my_db end end describe "orm" do it "should store orm" do cleaner = ::DatabaseCleaner::Base.new :a_orm cleaner.orm.should eq :a_orm end it "converts string to symbols" do cleaner = ::DatabaseCleaner::Base.new "mongoid" cleaner.orm.should eq :mongoid end it "is autodetected if orm is not provided" do cleaner = ::DatabaseCleaner::Base.new cleaner.should be_auto_detected end it "is autodetected if you specify :autodetect" do cleaner = ::DatabaseCleaner::Base.new "autodetect" cleaner.should be_auto_detected end it "should default to autodetect upon initalisation" do subject.should be_auto_detected end end end describe "db" do it "should default to :default" do subject.db.should eq :default end it "should return any stored db value" do subject.stub(:strategy_db=) subject.db = :test_db subject.db.should eq :test_db end it "should pass db to any specified strategy" do subject.should_receive(:strategy_db=).with(:a_new_db) subject.db = :a_new_db end end describe "strategy_db=" do let(:strategy) { mock_strategy } before(:each) do subject.strategy = strategy end it "should check that strategy supports db specification" do strategy.should_receive(:respond_to?).with(:db=).and_return(true) strategy.stub(:db=) subject.strategy_db = :a_db end context "when strategy supports db specification" do before(:each) { strategy.stub(:respond_to?).with(:db=).and_return true } it "should pass db to the strategy" do strategy.should_receive(:db=).with(:a_db) subject.strategy_db = :a_db end end context "when strategy doesn't supports db specification" do before(:each) { strategy.stub(:respond_to?).with(:db=).and_return false } it "should check to see if db is :default" do db = double("default") db.should_receive(:==).with(:default).and_return(true) subject.strategy_db = db end it "should raise an argument error when db isn't default" do db = double("a db") expect{ subject.strategy_db = db }.to raise_error ArgumentError end end end describe "clean_with" do let (:strategy) { double("strategy",:clean => true) } before(:each) { subject.stub(:create_strategy).with(anything).and_return(strategy) } it "should pass all arguments to create_strategy" do subject.should_receive(:create_strategy).with(:lorum, :dollar, :amet, :ipsum => "random").and_return(strategy) subject.clean_with :lorum, :dollar, :amet, { :ipsum => "random" } end it "should invoke clean on the created strategy" do strategy.should_receive(:clean) subject.clean_with :strategy end it "should return the strategy" do subject.clean_with( :strategy ).should eq strategy end end describe "clean_with!" do let (:strategy) { double("strategy",:clean => true) } before(:each) { subject.stub(:create_strategy).with(anything).and_return(strategy) } it "should pass all arguments to create_strategy" do subject.should_receive(:create_strategy).with(:lorum, :dollar, :amet, :ipsum => "random").and_return(strategy) subject.clean_with! :lorum, :dollar, :amet, { :ipsum => "random" } end it "should invoke clean on the created strategy" do strategy.should_receive(:clean) subject.clean_with! :strategy end it "should return the strategy" do subject.clean_with!( :strategy ).should eq strategy end end describe "create_strategy" do let(:strategy_class) { double("strategy_class",:new => double("instance")) } before :each do subject.stub(:orm_strategy).and_return(strategy_class) end it "should pass the first argument to orm_strategy" do subject.should_receive(:orm_strategy).with(:strategy).and_return(Object) subject.create_strategy :strategy end it "should pass the remainding argument to orm_strategy.new" do strategy_class.should_receive(:new).with(:params => {:lorum => "ipsum"}) subject.create_strategy :strategy, {:params => {:lorum => "ipsum"}} end it "should return the resulting strategy" do subject.create_strategy( :strategy ).should eq strategy_class.new end end describe "strategy=" do it "should proxy symbolised strategies to create_strategy" do subject.should_receive(:create_strategy).with(:symbol) subject.strategy = :symbol end it "should proxy params with symbolised strategies" do subject.should_receive(:create_strategy).with(:symbol,:param => "one") subject.strategy= :symbol, {:param => "one"} end it "should accept strategy objects" do expect{ subject.strategy = mock_strategy }.to_not raise_error end it "should raise argument error when params given with strategy Object" do expect{ subject.strategy = double("object"), {:param => "one"} }.to raise_error ArgumentError end it "should attempt to set strategy db" do subject.stub(:db).and_return(:my_db) subject.should_receive(:set_strategy_db).with(mock_strategy, :my_db) subject.strategy = mock_strategy end it "should return the stored strategy" do result = subject.strategy = mock_strategy result.should eq mock_strategy end end describe "strategy" do subject { ::DatabaseCleaner::Base.new :a_orm } it "returns a null strategy when strategy is not set and undetectable" do subject.strategy.should eq DatabaseCleaner::NullStrategy end it "returns the set strategy" do subject.strategy = mock_strategy subject.strategy.should eq mock_strategy end end describe "orm=" do it "should stored the desired orm" do subject.orm.should_not eq :desired_orm subject.orm = :desired_orm subject.orm.should eq :desired_orm end end describe "orm" do let(:mock_orm) { double("orm") } it "should return orm if orm set" do subject.instance_variable_set "@orm", mock_orm subject.orm.should eq mock_orm end context "orm isn't set" do before(:each) { subject.instance_variable_set "@orm", nil } it "should run autodetect if orm isn't set" do subject.should_receive(:autodetect) subject.orm end it "should return the result of autodetect if orm isn't set" do subject.stub(:autodetect).and_return(mock_orm) subject.orm.should eq mock_orm end end end describe "proxy methods" do let (:strategy) { double("strategy") } before(:each) do subject.stub(:strategy).and_return(strategy) end describe "start" do it "should proxy start to the strategy" do strategy.should_receive(:start) subject.start end end describe "clean" do it "should proxy clean to the strategy" do strategy.should_receive(:clean) subject.clean end end describe "clean!" do it "should proxy clean! to the strategy clean" do strategy.should_receive(:clean) subject.clean! end end describe "cleaning" do it "should proxy cleaning to the strategy" do strategy.should_receive(:cleaning) subject.cleaning { } end end end describe "auto_detected?" do it "should return true unless @autodetected is nil" do subject.instance_variable_set("@autodetected","not nil") subject.auto_detected?.should be_true end it "should return false if @autodetect is nil" do subject.instance_variable_set("@autodetected",nil) subject.auto_detected?.should be_false end end describe "orm_strategy" do let (:strategy_class) { double("strategy_class") } before(:each) do subject.stub(:orm_module).and_return(strategy_class) end context "in response to a LoadError" do before(:each) { subject.should_receive(:require).with(anything).and_raise(LoadError) } it "should raise UnknownStrategySpecified" do expect { subject.send(:orm_strategy,:a_strategy) }.to raise_error UnknownStrategySpecified end it "should ask orm_module if it will list available_strategies" do strategy_class.should_receive(:respond_to?).with(:available_strategies) subject.stub(:orm_module).and_return(strategy_class) expect { subject.send(:orm_strategy,:a_strategy) }.to raise_error UnknownStrategySpecified end it "should use available_strategies (for the error message) if its available" do strategy_class.stub(:respond_to?).with(:available_strategies).and_return(true) strategy_class.should_receive(:available_strategies).and_return([]) subject.stub(:orm_module).and_return(strategy_class) expect { subject.send(:orm_strategy,:a_strategy) }.to raise_error UnknownStrategySpecified end end it "should return the constant of the Strategy class requested" do strategy_strategy_class = double("strategy strategy_class") subject.stub(:require).with(anything).and_return(true) strategy_class.should_receive(:const_get).with("Cunningplan").and_return(strategy_strategy_class) subject.send(:orm_strategy, :cunningplan).should eq strategy_strategy_class end end describe 'set_default_orm_strategy' do it 'sets strategy to :transaction for ActiveRecord' do cleaner = DatabaseCleaner::Base.new(:active_record) cleaner.strategy.should be_instance_of DatabaseCleaner::ActiveRecord::Transaction end it 'sets strategy to :transaction for DataMapper' do cleaner = DatabaseCleaner::Base.new(:data_mapper) cleaner.strategy.should be_instance_of DatabaseCleaner::DataMapper::Transaction end it 'sets strategy to :truncation for MongoMapper' do cleaner = DatabaseCleaner::Base.new(:mongo_mapper) cleaner.strategy.should be_instance_of DatabaseCleaner::MongoMapper::Truncation end it 'sets strategy to :truncation for Mongoid' do cleaner = DatabaseCleaner::Base.new(:mongoid) cleaner.strategy.should be_instance_of DatabaseCleaner::Mongoid::Truncation end it 'sets strategy to :truncation for CouchPotato' do cleaner = DatabaseCleaner::Base.new(:couch_potato) cleaner.strategy.should be_instance_of DatabaseCleaner::CouchPotato::Truncation end it 'sets strategy to :transaction for Sequel' do cleaner = DatabaseCleaner::Base.new(:sequel) cleaner.strategy.should be_instance_of DatabaseCleaner::Sequel::Transaction end it 'sets strategy to :truncation for Moped' do cleaner = DatabaseCleaner::Base.new(:moped) cleaner.strategy.should be_instance_of DatabaseCleaner::Moped::Truncation end it 'sets strategy to :truncation for Ohm' do cleaner = DatabaseCleaner::Base.new(:ohm) cleaner.strategy.should be_instance_of DatabaseCleaner::Ohm::Truncation end it 'sets strategy to :truncation for Redis' do cleaner = DatabaseCleaner::Base.new(:redis) cleaner.strategy.should be_instance_of DatabaseCleaner::Redis::Truncation end it 'sets strategy to :transaction for Neo4j' do cleaner = DatabaseCleaner::Base.new(:neo4j) cleaner.strategy.should be_instance_of DatabaseCleaner::Neo4j::Transaction end end end end database_cleaner-1.7.0/spec/database_cleaner/configuration_spec.rb000066400000000000000000000276631326617530700254010ustar00rootroot00000000000000require 'spec_helper' module ArrayHelper def zipmap(array, vals) Hash[*(array.zip(vals).flatten)] end module_function :zipmap end module DatabaseCleaner class << self def reset @cleaners = nil @connections = nil end # hackey, hack.. connections needs to stick around until I can properly deprecate the API def connections_stub(array) @cleaners = ArrayHelper.zipmap((1..array.size).to_a, array) @connections = array end end end describe ::DatabaseCleaner do before(:each) { ::DatabaseCleaner.reset } context "orm specification" do it "should not accept unrecognised orms" do expect { ::DatabaseCleaner[nil] }.to raise_error(::DatabaseCleaner::NoORMDetected) end it "should accept :active_record" do cleaner = ::DatabaseCleaner[:active_record] cleaner.should be_a(::DatabaseCleaner::Base) cleaner.orm.should eq :active_record ::DatabaseCleaner.connections.size.should eq 1 end it "should accept :data_mapper" do cleaner = ::DatabaseCleaner[:data_mapper] cleaner.should be_a(::DatabaseCleaner::Base) cleaner.orm.should eq :data_mapper ::DatabaseCleaner.connections.size.should eq 1 end it "should accept :mongo_mapper" do cleaner = ::DatabaseCleaner[:mongo_mapper] cleaner.should be_a(::DatabaseCleaner::Base) cleaner.orm.should eq :mongo_mapper ::DatabaseCleaner.connections.size.should eq 1 end it "should accept :couch_potato" do cleaner = ::DatabaseCleaner[:couch_potato] cleaner.should be_a(::DatabaseCleaner::Base) cleaner.orm.should eq :couch_potato ::DatabaseCleaner.connections.size.should eq 1 end it "should accept :moped" do cleaner = ::DatabaseCleaner[:moped] cleaner.should be_a(::DatabaseCleaner::Base) cleaner.orm.should eq :moped ::DatabaseCleaner.connections.size.should eq 1 end it 'accepts :ohm' do cleaner = ::DatabaseCleaner[:ohm] cleaner.should be_a(::DatabaseCleaner::Base) cleaner.orm.should eq :ohm ::DatabaseCleaner.connections.size.should eq 1 end end it "should accept multiple orm's" do ::DatabaseCleaner[:couch_potato] ::DatabaseCleaner[:data_mapper] ::DatabaseCleaner.connections.size.should eq 2 ::DatabaseCleaner.connections[0].orm.should eq :couch_potato ::DatabaseCleaner.connections[1].orm.should eq :data_mapper end context "connection/db specification" do it "should accept a connection parameter and store it" do cleaner = ::DatabaseCleaner[:active_record, {:connection => :first_connection}] cleaner.should be_a(::DatabaseCleaner::Base) cleaner.orm.should eq :active_record cleaner.db.should eq :first_connection end it "should accept multiple connections for a single orm" do ::DatabaseCleaner[:data_mapper,{:connection => :first_db}] ::DatabaseCleaner[:data_mapper,{:connection => :second_db}] ::DatabaseCleaner.connections.size.should eq 2 ::DatabaseCleaner.connections[0].orm.should eq :data_mapper ::DatabaseCleaner.connections[0].db.should eq :first_db ::DatabaseCleaner.connections[1].orm.should eq :data_mapper ::DatabaseCleaner.connections[1].db.should eq :second_db end it "should accept multiple connections and multiple orms" do ::DatabaseCleaner[:data_mapper, {:connection => :first_db} ] ::DatabaseCleaner[:active_record,{:connection => :second_db}] ::DatabaseCleaner[:active_record,{:connection => :first_db} ] ::DatabaseCleaner[:data_mapper, {:connection => :second_db}] ::DatabaseCleaner.connections.size.should eq 4 ::DatabaseCleaner.connections[0].orm.should eq :data_mapper ::DatabaseCleaner.connections[0].db.should eq :first_db ::DatabaseCleaner.connections[1].orm.should eq :active_record ::DatabaseCleaner.connections[1].db.should eq :second_db ::DatabaseCleaner.connections[2].orm.should eq :active_record ::DatabaseCleaner.connections[2].db.should eq :first_db ::DatabaseCleaner.connections[3].orm.should eq :data_mapper ::DatabaseCleaner.connections[3].db.should eq :second_db end end context "connection/db retrieval" do it "should retrieve a db rather than create a new one" do pending connection = ::DatabaseCleaner[:active_record].strategy = :truncation ::DatabaseCleaner[:active_record].should eq connection end end context "class methods" do subject { ::DatabaseCleaner } it "should give me a default (autodetection) databasecleaner by default" do cleaner = double("cleaner").as_null_object ::DatabaseCleaner::Base.stub(:new).and_return(cleaner) ::DatabaseCleaner.connections.should eq [cleaner] end end context "single orm single connection" do let(:connection) { ::DatabaseCleaner.connections.first } it "should proxy strategy=" do stratagum = double("stratagum") connection.should_receive(:strategy=).with(stratagum) ::DatabaseCleaner.strategy = stratagum end it "should proxy orm=" do orm = double("orm") connection.should_receive(:orm=).with(orm) ::DatabaseCleaner.orm = orm end it "should proxy start" do connection.should_receive(:start) ::DatabaseCleaner.start end it "should proxy clean" do connection.should_receive(:clean) ::DatabaseCleaner.clean end it 'should proxy cleaning' do connection.should_receive(:cleaning) ::DatabaseCleaner.cleaning { } end it "should proxy clean_with" do stratagem = double("stratgem") connection.should_receive(:clean_with).with(stratagem, {}) ::DatabaseCleaner.clean_with stratagem, {} end end context "multiple connections" do #these are relativly simple, all we need to do is make sure all connections are cleaned/started/cleaned_with appropriatly. context "simple proxy methods" do let(:active_record) { double("active_mock") } let(:data_mapper) { double("data_mock") } before(:each) do ::DatabaseCleaner.stub(:connections).and_return([active_record,data_mapper]) end it "should proxy orm to all connections" do active_record.should_receive(:orm=) data_mapper.should_receive(:orm=) ::DatabaseCleaner.orm = double("orm") end it "should proxy start to all connections" do active_record.should_receive(:start) data_mapper.should_receive(:start) ::DatabaseCleaner.start end it "should proxy clean to all connections" do active_record.should_receive(:clean) data_mapper.should_receive(:clean) ::DatabaseCleaner.clean end it "should initiate cleaning on each connection, yield, and finish cleaning each connection" do [active_record, data_mapper].each do |connection| mc = class << connection; self; end mc.send(:attr_reader, :started, :cleaned) mc.send(:define_method, 'cleaning') do |&block| @started = true block.call @cleaned = true end end ::DatabaseCleaner.cleaning do active_record.started.should == true data_mapper.started.should == true active_record.cleaned.should == nil data_mapper.cleaned.should == nil @yielded = true end active_record.cleaned.should == true data_mapper.cleaned.should == true end it "should proxy clean_with to all connections" do stratagem = double("stratgem") active_record.should_receive(:clean_with).with(stratagem) data_mapper.should_receive(:clean_with).with(stratagem) ::DatabaseCleaner.clean_with stratagem end end # ah now we have some difficulty, we mustn't allow duplicate connections to exist, but they could # plausably want to force orm/strategy change on two sets of orm that differ only on db context "multiple orm proxy methods" do pending "should proxy orm to all connections and remove duplicate connections" do active_record_1 = double("active_mock_on_db_one").as_null_object active_record_2 = double("active_mock_on_db_two").as_null_object data_mapper_1 = double("data_mock_on_db_one").as_null_object ::DatabaseCleaner.connections_stub [active_record_1,active_record_2,data_mapper_1] active_record_1.should_receive(:orm=).with(:data_mapper) active_record_2.should_receive(:orm=).with(:data_mapper) data_mapper_1.should_receive(:orm=).with(:data_mapper) active_record_1.should_receive(:==).with(data_mapper_1).and_return(true) ::DatabaseCleaner.connections.size.should eq 3 ::DatabaseCleaner.orm = :data_mapper ::DatabaseCleaner.connections.size.should eq 2 end it "should proxy strategy to all connections and remove duplicate connections" do active_record_1 = double("active_mock_strategy_one").as_null_object active_record_2 = double("active_mock_strategy_two").as_null_object strategy = double("strategy") ::DatabaseCleaner.connections_stub [active_record_1,active_record_2] active_record_1.should_receive(:strategy=).with(strategy) active_record_2.should_receive(:strategy=).with(strategy) active_record_1.should_receive(:==).with(active_record_2).and_return(true) ::DatabaseCleaner.connections.size.should eq 2 ::DatabaseCleaner.strategy = strategy ::DatabaseCleaner.connections.size.should eq 1 end end end describe "remove_duplicates" do it "should remove duplicates if they are identical" do orm = double("orm") connection = double("a datamapper connection", :orm => orm ) ::DatabaseCleaner.connections_stub [connection,connection,connection] ::DatabaseCleaner.remove_duplicates ::DatabaseCleaner.connections.size.should eq 1 end end describe "app_root" do it "should default to Dir.pwd" do DatabaseCleaner.app_root.should eq Dir.pwd end it "should store specific paths" do DatabaseCleaner.app_root = '/path/to' DatabaseCleaner.app_root.should eq '/path/to' end end describe "orm_module" do subject { ::DatabaseCleaner } it "should return DatabaseCleaner::ActiveRecord for :active_record" do ::DatabaseCleaner::ActiveRecord = double("ar module") unless defined? ::DatabaseCleaner::ActiveRecord subject.orm_module(:active_record).should eq DatabaseCleaner::ActiveRecord end it "should return DatabaseCleaner::DataMapper for :data_mapper" do ::DatabaseCleaner::DataMapper = double("dm module") unless defined? ::DatabaseCleaner::DataMapper subject.orm_module(:data_mapper).should eq DatabaseCleaner::DataMapper end it "should return DatabaseCleaner::MongoMapper for :mongo_mapper" do ::DatabaseCleaner::MongoMapper = double("mm module") unless defined? ::DatabaseCleaner::MongoMapper subject.orm_module(:mongo_mapper).should eq DatabaseCleaner::MongoMapper end it "should return DatabaseCleaner::Mongoid for :mongoid" do ::DatabaseCleaner::Mongoid = double("mongoid module") unless defined? ::DatabaseCleaner::Mongoid subject.orm_module(:mongoid).should eq DatabaseCleaner::Mongoid end it "should return DatabaseCleaner::Mongo for :mongo" do ::DatabaseCleaner::Mongo = double("mongo module") unless defined? ::DatabaseCleaner::Mongo subject.orm_module(:mongo).should eq DatabaseCleaner::Mongo end it "should return DatabaseCleaner::CouchPotato for :couch_potato" do ::DatabaseCleaner::CouchPotato = double("cp module") unless defined? ::DatabaseCleaner::CouchPotato subject.orm_module(:couch_potato).should eq DatabaseCleaner::CouchPotato end it "should return DatabaseCleaner::Neo4j for :neo4j" do ::DatabaseCleaner::Neo4j = double("nj module") unless defined? ::DatabaseCleaner::Neo4j subject.orm_module(:neo4j).should eq DatabaseCleaner::Neo4j end end end database_cleaner-1.7.0/spec/database_cleaner/couch_potato/000077500000000000000000000000001326617530700236445ustar00rootroot00000000000000database_cleaner-1.7.0/spec/database_cleaner/couch_potato/truncation_spec.rb000066400000000000000000000020531326617530700273710ustar00rootroot00000000000000require File.dirname(__FILE__) + '/../../spec_helper' require 'database_cleaner/couch_potato/truncation' require 'couch_potato' module DatabaseCleaner module CouchPotato describe Truncation do let(:database) { double('database') } before(:each) do ::CouchPotato.stub(:couchrest_database).and_return(database) end it "should re-create the database" do database.should_receive(:recreate!) Truncation.new.clean end it "should raise an error when the :only option is used" do running { Truncation.new(:only => ['document-type']) }.should raise_error(ArgumentError) end it "should raise an error when the :except option is used" do running { Truncation.new(:except => ['document-type']) }.should raise_error(ArgumentError) end it "should raise an error when invalid options are provided" do running { Truncation.new(:foo => 'bar') }.should raise_error(ArgumentError) end end end end database_cleaner-1.7.0/spec/database_cleaner/data_mapper/000077500000000000000000000000001326617530700234325ustar00rootroot00000000000000database_cleaner-1.7.0/spec/database_cleaner/data_mapper/base_spec.rb000066400000000000000000000012751326617530700257100ustar00rootroot00000000000000require 'spec_helper' require 'database_cleaner/data_mapper/base' require 'database_cleaner/shared_strategy' module DatabaseCleaner describe DataMapper do it { should respond_to(:available_strategies) } end module DataMapper class ExampleStrategy include ::DatabaseCleaner::DataMapper::Base end describe ExampleStrategy do it_should_behave_like "a generic strategy" it { should respond_to(:db) } it { should respond_to(:db=) } it "should store my desired db" do subject.db = :my_db subject.db.should eq :my_db end it "should default to :default" do subject.db.should eq :default end end end end database_cleaner-1.7.0/spec/database_cleaner/data_mapper/transaction_spec.rb000066400000000000000000000010201326617530700273070ustar00rootroot00000000000000require File.dirname(__FILE__) + '/../../spec_helper' require 'database_cleaner/data_mapper/transaction' require 'database_cleaner/shared_strategy' #require 'data_mapper' module DatabaseCleaner module DataMapper describe Transaction do it_should_behave_like "a generic strategy" it_should_behave_like "a generic transaction strategy" describe "start" do it "should start a transaction" end describe "clean" do it "should finish a transaction" end end end end database_cleaner-1.7.0/spec/database_cleaner/data_mapper/truncation/000077500000000000000000000000001326617530700256205ustar00rootroot00000000000000database_cleaner-1.7.0/spec/database_cleaner/data_mapper/truncation/sqlite3_spec.rb000066400000000000000000000021001326617530700305340ustar00rootroot00000000000000require 'spec_helper' require 'dm-core' require 'dm-sqlite-adapter' require File.expand_path('../../../../support/data_mapper/sqlite3_setup', __FILE__) require 'database_cleaner/data_mapper/truncation' module DataMapper module ConnectionAdapters describe do before(:all) { data_mapper_sqlite3_setup } let(:adapter) { DataMapperSQLite3Adapter } let(:connection) do data_mapper_sqlite3_connection end before(:each) do connection.truncate_tables(DataMapper::Model.descendants.map { |d| d.storage_names[:default] || d.name.underscore }) end describe "#truncate_table" do it "truncates the table" do 2.times { DmUser.create } connection.truncate_table(DmUser.storage_names[:default]) DmUser.count.should eq 0 end it "resets AUTO_INCREMENT index of table" do 2.times { DmUser.create } DmUser.destroy connection.truncate_table(DmUser.storage_names[:default]) DmUser.create.id.should eq 1 end end end end end database_cleaner-1.7.0/spec/database_cleaner/data_mapper/truncation_spec.rb000066400000000000000000000004431326617530700271600ustar00rootroot00000000000000require 'database_cleaner/data_mapper/truncation' require 'database_cleaner/shared_strategy' module DatabaseCleaner module DataMapper describe Truncation do it_should_behave_like "a generic strategy" it_should_behave_like "a generic truncation strategy" end end end database_cleaner-1.7.0/spec/database_cleaner/generic/000077500000000000000000000000001326617530700225715ustar00rootroot00000000000000database_cleaner-1.7.0/spec/database_cleaner/generic/base_spec.rb000066400000000000000000000032311326617530700250410ustar00rootroot00000000000000require 'spec_helper' require 'database_cleaner/shared_strategy' require 'database_cleaner/generic/base' require 'active_record' module ::DatabaseCleaner module Generic class ExampleStrategy include ::DatabaseCleaner::Generic::Base def start; end end describe ExampleStrategy do context "class methods" do subject { ExampleStrategy } describe "#available_strategies" do it "should have available strategies" do expect(subject.available_strategies).to be_empty end end end it_should_behave_like "a generic strategy" describe "#db" do it "should be :default" do expect(subject.db).to eql(:default) end end describe "#cleaning" do let (:connection) { double("connection") } let (:strategy) { ExampleStrategy.new } before do # DatabaseCleaner.strategy = :truncation connection.stub(:disable_referential_integrity).and_yield connection.stub(:database_cleaner_view_cache).and_return([]) connection.stub(:database_cleaner_table_cache).and_return([]) ::ActiveRecord::Base.stub(:connection).and_return(connection) end it "calls #clean even if there is an exception" do strategy.should_receive :clean expect do strategy.cleaning do raise NoMethodError end end.to raise_exception(NoMethodError) end it "calls #clean after processing the block" do strategy.should_receive :clean strategy.cleaning do end end end end end end database_cleaner-1.7.0/spec/database_cleaner/generic/truncation_spec.rb000066400000000000000000000074261326617530700263270ustar00rootroot00000000000000require 'spec_helper' require 'database_cleaner/generic/truncation' module ::DatabaseCleaner module Generic class TruncationExample include ::DatabaseCleaner::Generic::Truncation def only @only end def except @tables_to_exclude end def reset_ids? !!@reset_ids end def pre_count? !!@pre_count end end class MigrationExample < TruncationExample def migration_storage_names %w[migration_storage_name] end end describe TruncationExample do subject(:truncation_example) { TruncationExample.new } it "will start" do expect { truncation_example.start }.to_not raise_error end it "expects clean to be implemented later" do expect { truncation_example.clean }.to raise_error(NotImplementedError) end context "private methods" do it { should_not respond_to(:tables_to_truncate) } it 'expects #tables_to_truncate to be implemented later' do expect{ truncation_example.send :tables_to_truncate }.to raise_error(NotImplementedError) end it { should_not respond_to(:migration_storage_names) } its(:migration_storage_names) { should be_empty } end describe "initialize" do it { expect{ subject }.to_not raise_error } it "should accept a hash of options" do expect{ TruncationExample.new {} }.to_not raise_error end it { expect{ TruncationExample.new( { :a_random_param => "should raise ArgumentError" } ) }.to raise_error(ArgumentError) } it { expect{ TruncationExample.new( { :except => "something",:only => "something else" } ) }.to raise_error(ArgumentError) } it { expect{ TruncationExample.new( { :only => "something" } ) }.to_not raise_error } it { expect{ TruncationExample.new( { :except => "something" } ) }.to_not raise_error } it { expect{ TruncationExample.new( { :pre_count => "something" } ) }.to_not raise_error } it { expect{ TruncationExample.new( { :reset_ids => "something" } ) }.to_not raise_error } context "" do subject { TruncationExample.new( { :only => ["something"] } ) } its(:only) { should eq ["something"] } its(:except) { should eq [] } end context "" do subject { TruncationExample.new( { :except => ["something"] } ) } its(:only) { should eq nil } its(:except) { should include("something") } end context "" do subject { TruncationExample.new( { :reset_ids => ["something"] } ) } its(:reset_ids?) { should eq true } end context "" do subject { TruncationExample.new( { :reset_ids => nil } ) } its(:reset_ids?) { should eq false } end context "" do subject { TruncationExample.new( { :pre_count => ["something"] } ) } its(:pre_count?) { should eq true } end context "" do subject { TruncationExample.new( { :pre_count => nil } ) } its(:pre_count?) { should eq false } end context "" do subject { MigrationExample.new } its(:only) { should eq nil } its(:except) { should eq %w[migration_storage_name] } end context "" do EXCEPT_TABLES = ["something"] subject { MigrationExample.new( { :except => EXCEPT_TABLES } ) } it "should not modify the array of excepted tables" do subject.except.should include("migration_storage_name") EXCEPT_TABLES.should_not include("migration_storage_name") end end end end end end database_cleaner-1.7.0/spec/database_cleaner/mongo/000077500000000000000000000000001326617530700222745ustar00rootroot00000000000000database_cleaner-1.7.0/spec/database_cleaner/mongo/mongo_examples.rb000066400000000000000000000007631326617530700256440ustar00rootroot00000000000000module MongoTest class ThingBase def self.collection @connection ||= ::Mongo::Connection.new('127.0.0.1') @db ||= @connection.db('database_cleaner_specs') @mongo ||= @db.collection(name) || @db.create_collection(name) end def self.count @mongo.count end def initialize(attrs={}) @attrs = attrs end def save! self.class.collection.insert(@attrs) end end class Widget < ThingBase end class Gadget < ThingBase end end database_cleaner-1.7.0/spec/database_cleaner/mongo/truncation_spec.rb000066400000000000000000000046711326617530700260310ustar00rootroot00000000000000require File.dirname(__FILE__) + '/../../spec_helper' require 'mongo' require 'database_cleaner/mongo/truncation' require File.dirname(__FILE__) + '/mongo_examples' module DatabaseCleaner module Mongo describe Truncation do let(:args) {{}} let(:truncation) { described_class.new(args).tap { |t| t.db=@db } } #doing this in the file root breaks autospec, doing it before(:all) just fails the specs before(:all) do @connection = ::Mongo::Connection.new('127.0.0.1') @test_db = 'database_cleaner_specs' @db = @connection.db(@test_db) end after(:each) do @connection.drop_database(@test_db) end def ensure_counts(expected_counts) # I had to add this sanity_check garbage because I was getting non-determinisc results from mongo at times.. # very odd and disconcerting... expected_counts.each do |model_class, expected_count| model_class.count.should eq(expected_count), "#{model_class} expected to have a count of #{expected_count} but was #{model_class.count}" end end def create_widget(attrs={}) MongoTest::Widget.new({:name => 'some widget'}.merge(attrs)).save! end def create_gadget(attrs={}) MongoTest::Gadget.new({:name => 'some gadget'}.merge(attrs)).save! end xit "truncates all collections by default" do create_widget create_gadget ensure_counts(MongoTest::Widget => 1, MongoTest::Gadget => 1) truncation.clean ensure_counts(MongoTest::Widget => 0, MongoTest::Gadget => 0) end context "when collections are provided to the :only option" do let(:args) {{:only => ['MongoTest::Widget']}} xit "only truncates the specified collections" do create_widget create_gadget ensure_counts(MongoTest::Widget => 1, MongoTest::Gadget => 1) truncation.clean ensure_counts(MongoTest::Widget => 0, MongoTest::Gadget => 1) end end context "when collections are provided to the :except option" do let(:args) {{:except => ['MongoTest::Widget']}} xit "truncates all but the specified collections" do create_widget create_gadget ensure_counts(MongoTest::Widget => 1, MongoTest::Gadget => 1) truncation.clean ensure_counts(MongoTest::Widget => 1, MongoTest::Gadget => 0) end end end end end database_cleaner-1.7.0/spec/database_cleaner/mongo_mapper/000077500000000000000000000000001326617530700236405ustar00rootroot00000000000000database_cleaner-1.7.0/spec/database_cleaner/mongo_mapper/base_spec.rb000066400000000000000000000013171326617530700261130ustar00rootroot00000000000000require 'spec_helper' require 'database_cleaner/mongo_mapper/base' require 'database_cleaner/shared_strategy' module DatabaseCleaner describe MongoMapper do it { should respond_to(:available_strategies) } end module MongoMapper class ExampleStrategy include ::DatabaseCleaner::MongoMapper::Base end describe ExampleStrategy do it_should_behave_like "a generic strategy" describe "db" do it { should respond_to(:db=) } it "should store my desired db" do subject.db = :my_db subject.db.should eq :my_db end it "should default to :default" do subject.db.should eq :default end end end end end database_cleaner-1.7.0/spec/database_cleaner/mongo_mapper/mongo_examples.rb000066400000000000000000000002161326617530700272010ustar00rootroot00000000000000class Widget include ::MongoMapper::Document key :name, String end class Gadget include ::MongoMapper::Document key :name, String end database_cleaner-1.7.0/spec/database_cleaner/mongo_mapper/truncation_spec.rb000066400000000000000000000051171326617530700273710ustar00rootroot00000000000000require File.dirname(__FILE__) + '/../../spec_helper' require 'mongo_mapper' require 'database_cleaner/mongo_mapper/truncation' require File.dirname(__FILE__) + '/mongo_examples' module DatabaseCleaner module MongoMapper describe Truncation do #doing this in the file root breaks autospec, doing it before(:all) just fails the specs before(:all) do ::MongoMapper.connection = ::Mongo::Connection.new('127.0.0.1') @test_db = 'database_cleaner_specs' ::MongoMapper.database = @test_db end before(:each) do ::MongoMapper.connection.drop_database(@test_db) end def ensure_counts(expected_counts) # I had to add this sanity_check garbage because I was getting non-determinisc results from mongomapper at times.. # very odd and disconcerting... sanity_check = expected_counts.delete(:sanity_check) begin expected_counts.each do |model_class, expected_count| model_class.count.should eq(expected_count), "#{model_class} expected to have a count of #{expected_count} but was #{model_class.count}" end rescue RSpec::Expectations::ExpectationNotMetError => e raise !sanity_check ? e : RSpec::ExpectationNotMetError::ExpectationNotMetError.new("SANITY CHECK FAILURE! This should never happen here: #{e.message}") end end def create_widget(attrs={}) Widget.new({:name => 'some widget'}.merge(attrs)).save! end def create_gadget(attrs={}) Gadget.new({:name => 'some gadget'}.merge(attrs)).save! end xit "truncates all collections by default" do create_widget create_gadget ensure_counts(Widget => 1, Gadget => 1, :sanity_check => true) Truncation.new.clean ensure_counts(Widget => 0, Gadget => 0) end context "when collections are provided to the :only option" do xit "only truncates the specified collections" do create_widget create_gadget ensure_counts(Widget => 1, Gadget => 1, :sanity_check => true) Truncation.new(:only => ['widgets']).clean ensure_counts(Widget => 0, Gadget => 1) end end context "when collections are provided to the :except option" do xit "truncates all but the specified collections" do create_widget create_gadget ensure_counts(Widget => 1, Gadget => 1, :sanity_check => true) Truncation.new(:except => ['widgets']).clean ensure_counts(Widget => 1, Gadget => 0) end end end end end database_cleaner-1.7.0/spec/database_cleaner/moped/000077500000000000000000000000001326617530700222615ustar00rootroot00000000000000database_cleaner-1.7.0/spec/database_cleaner/moped/moped_examples.rb000066400000000000000000000011271326617530700256110ustar00rootroot00000000000000module MopedTest class ThingBase def self.collection @db ||= 'database_cleaner_specs' @session ||= ::Moped::Session.new(['127.0.0.1:27017'], database: @db) @collection ||= @session[name] end def self.count @collection.find.count end def initialize(attrs={}) @attrs = attrs end def save! self.class.collection.insert(@attrs) end end class Widget < ThingBase end class Gadget < ThingBase end class System < ThingBase def self.collection super @collection = @session['system_logs'] end end end database_cleaner-1.7.0/spec/database_cleaner/moped/truncation_spec.rb000066400000000000000000000051731326617530700260140ustar00rootroot00000000000000require File.dirname(__FILE__) + '/../../spec_helper' require 'moped' require 'database_cleaner/moped/truncation' require File.dirname(__FILE__) + '/moped_examples' module DatabaseCleaner module Moped describe Truncation do let(:args) {{}} let(:truncation) { described_class.new(args) } #doing this in the file root breaks autospec, doing it before(:all) just fails the specs before(:all) do @test_db = 'database_cleaner_specs' @session = ::Moped::Session.new(['127.0.0.1:27017'], database: @test_db) end before(:each) do truncation.db = @test_db end after(:each) do @session.drop end def ensure_counts(expected_counts) # I had to add this sanity_check garbage because I was getting non-determinisc results from mongo at times.. # very odd and disconcerting... expected_counts.each do |model_class, expected_count| model_class.count.should eq(expected_count), "#{model_class} expected to have a count of #{expected_count} but was #{model_class.count}" end end def create_widget(attrs={}) MopedTest::Widget.new({:name => 'some widget'}.merge(attrs)).save! end def create_gadget(attrs={}) MopedTest::Gadget.new({:name => 'some gadget'}.merge(attrs)).save! end def create_system(attrs={}) MopedTest::System.new({:name => 'some system'}.merge(attrs)).save! end it "truncates all collections by default" do create_widget create_gadget create_system ensure_counts(MopedTest::Widget => 1, MopedTest::Gadget => 1, MopedTest::System => 1) truncation.clean ensure_counts(MopedTest::Widget => 0, MopedTest::Gadget => 0, MopedTest::System => 0) end context "when collections are provided to the :only option" do let(:args) {{:only => ['MopedTest::Widget']}} it "only truncates the specified collections" do create_widget create_gadget ensure_counts(MopedTest::Widget => 1, MopedTest::Gadget => 1) truncation.clean ensure_counts(MopedTest::Widget => 0, MopedTest::Gadget => 1) end end context "when collections are provided to the :except option" do let(:args) {{:except => ['MopedTest::Widget']}} it "truncates all but the specified collections" do create_widget create_gadget ensure_counts(MopedTest::Widget => 1, MopedTest::Gadget => 1) truncation.clean ensure_counts(MopedTest::Widget => 1, MopedTest::Gadget => 0) end end end end end database_cleaner-1.7.0/spec/database_cleaner/neo4j/000077500000000000000000000000001326617530700221745ustar00rootroot00000000000000database_cleaner-1.7.0/spec/database_cleaner/neo4j/base_spec.rb000066400000000000000000000024701326617530700244500ustar00rootroot00000000000000require 'spec_helper' require 'database_cleaner/neo4j/base' require 'database_cleaner/shared_strategy' module DatabaseCleaner describe Neo4j do it { should respond_to(:available_strategies) } end module Neo4j class ExampleStrategy include ::DatabaseCleaner::Neo4j::Base end describe ExampleStrategy do it_should_behave_like "a generic strategy" it { should respond_to(:db) } it { should respond_to(:db=) } it "should store my describe db" do db_conf = {:connection => {:type => :server_db, :path => 'http://localhost:7474'}} subject.db = db_conf subject.db.should eq db_conf end it "should respect additional connection parameters" do db_conf = {:type => :server_db, :path => 'http://localhost:7474', basic_auth: {username: 'user', password: 'pass'}} subject.db = db_conf stub_const("Neo4j::Session", double()).should_receive(:open).with(:server_db, 'http://localhost:7474', {basic_auth: {username: 'user', password: 'pass'}}) { true } subject.start end it "should default to nil" do subject.db.should be_nil end it "should return default configuration" do subject.database.should eq(:type => :server_db, :path => 'http://localhost:7475/') end end end end database_cleaner-1.7.0/spec/database_cleaner/neo4j/transaction_spec.rb000066400000000000000000000011401326617530700260540ustar00rootroot00000000000000require File.dirname(__FILE__) + '/../../spec_helper' require 'neo4j-core' require 'database_cleaner/neo4j/transaction' module DatabaseCleaner module Neo4j describe Transaction do before(:all) do DatabaseCleaner[:neo4j, :connection => {:type => :server_db, :path => 'http://localhost:7474'}] end it_should_behave_like "a generic strategy" it_should_behave_like "a generic transaction strategy" describe "start" do it "should start a transaction" end describe "clean" do it "should finish a transaction" end end end end database_cleaner-1.7.0/spec/database_cleaner/null_strategy_spec.rb000066400000000000000000000012461326617530700254130ustar00rootroot00000000000000require 'spec_helper' module DatabaseCleaner describe NullStrategy do it 'responds to .start' do expect { NullStrategy.start }.not_to raise_error(NoMethodError) end it 'responds to .clean' do expect { NullStrategy.clean }.not_to raise_error(NoMethodError) end describe '.cleaning' do it 'fails without a block' do expect { NullStrategy.cleaning }.to raise_error(LocalJumpError) end it 'no-ops with a block' do effect = double expect(effect).to receive(:occur).once NullStrategy.cleaning do effect.occur end end end end end database_cleaner-1.7.0/spec/database_cleaner/ohm/000077500000000000000000000000001326617530700217405ustar00rootroot00000000000000database_cleaner-1.7.0/spec/database_cleaner/ohm/truncation_spec.rb000066400000000000000000000035131326617530700254670ustar00rootroot00000000000000require File.dirname(__FILE__) + '/../../spec_helper' require 'ohm' require 'database_cleaner/ohm/truncation' module DatabaseCleaner module Ohm class Widget < ::Ohm::Model attribute :name end class Gadget < ::Ohm::Model attribute :name end describe Truncation do before(:all) do config = YAML::load(File.open("#{File.dirname(__FILE__)}/../../../examples/config/redis.yml")) ::Ohm.connect :url => config['test']['url'] @redis = ::Ohm.redis end before(:each) do @redis.flushdb end it "should flush the database" do Truncation.new.clean end def create_widget(attrs={}) Widget.new({:name => 'some widget'}.merge(attrs)).save end def create_gadget(attrs={}) Gadget.new({:name => 'some gadget'}.merge(attrs)).save end it "truncates all keys by default" do create_widget create_gadget @redis.keys.size.should eq 6 Truncation.new.clean @redis.keys.size.should eq 0 end context "when keys are provided to the :only option" do it "only truncates the specified keys" do create_widget create_gadget @redis.keys.size.should eq 6 Truncation.new(:only => ['*Widget*']).clean @redis.keys.size.should eq 3 @redis.get('DatabaseCleaner::Ohm::Gadget:id').should eq '1' end end context "when keys are provided to the :except option" do it "truncates all but the specified keys" do create_widget create_gadget @redis.keys.size.should eq 6 Truncation.new(:except => ['*Widget*']).clean @redis.keys.size.should eq 3 @redis.get('DatabaseCleaner::Ohm::Widget:id').should eq '1' end end end end end database_cleaner-1.7.0/spec/database_cleaner/redis/000077500000000000000000000000001326617530700222635ustar00rootroot00000000000000database_cleaner-1.7.0/spec/database_cleaner/redis/base_spec.rb000066400000000000000000000020531326617530700245340ustar00rootroot00000000000000require 'spec_helper' require 'redis' require 'database_cleaner/redis/base' require 'database_cleaner/shared_strategy' module DatabaseCleaner describe Redis do it { should respond_to(:available_strategies) } end module Redis class ExampleStrategy include ::DatabaseCleaner::Redis::Base end describe ExampleStrategy do it_should_behave_like "a generic strategy" it { should respond_to(:db) } it { should respond_to(:db=) } context "when passing url" do it "should store my describe db" do url = 'redis://localhost:6379/2' subject.db = 'redis://localhost:6379/2' subject.db.should eq url end end context "when passing connection" do it "should store my describe db" do connection = ::Redis.new :url => 'redis://localhost:6379/2' subject.db = connection subject.db.should eq connection end end it "should default to :default" do subject.db.should eq :default end end end end database_cleaner-1.7.0/spec/database_cleaner/redis/truncation_spec.rb000066400000000000000000000031061326617530700260100ustar00rootroot00000000000000require File.dirname(__FILE__) + '/../../spec_helper' require 'redis' require 'database_cleaner/redis/truncation' module DatabaseCleaner module Redis describe Truncation do before(:all) do config = YAML::load(File.open("#{File.dirname(__FILE__)}/../../../examples/config/redis.yml")) @redis = ::Redis.new :url => config['test']['url'] end before(:each) do @redis.flushdb end it "should flush the database" do Truncation.new.clean end def create_widget(attrs={}) @redis.set 'Widget', 1 end def create_gadget(attrs={}) @redis.set 'Gadget', 1 end it "truncates all keys by default" do create_widget create_gadget @redis.keys.size.should eq 2 Truncation.new.clean @redis.keys.size.should eq 0 end context "when keys are provided to the :only option" do it "only truncates the specified keys" do create_widget create_gadget @redis.keys.size.should eq 2 Truncation.new(:only => ['Widge*']).clean @redis.keys.size.should eq 1 @redis.get('Gadget').should eq '1' end end context "when keys are provided to the :except option" do it "truncates all but the specified keys" do create_widget create_gadget @redis.keys.size.should eq 2 Truncation.new(:except => ['Widg*']).clean @redis.keys.size.should eq 1 @redis.get('Widget').should eq '1' end end end end end database_cleaner-1.7.0/spec/database_cleaner/safeguard_spec.rb000066400000000000000000000051631326617530700244620ustar00rootroot00000000000000require 'spec_helper' require 'active_record' require 'database_cleaner/active_record/transaction' module DatabaseCleaner describe Safeguard do let(:strategy) { DatabaseCleaner::ActiveRecord::Transaction } let(:cleaner) { Base.new(:autodetect) } before { allow_any_instance_of(strategy).to receive(:start) } describe 'DATABASE_URL is set' do before { stub_const('ENV', 'DATABASE_URL' => database_url) } describe 'to any value' do let(:database_url) { 'postgres://remote.host' } it 'raises' do expect { cleaner.start }.to raise_error(Safeguard::Error::RemoteDatabaseUrl) end end describe 'to a localhost url' do let(:database_url) { 'postgres://localhost' } it 'does not raise' do expect { cleaner.start }.to_not raise_error end end describe 'to a 127.0.0.1 url' do let(:database_url) { 'postgres://127.0.0.1' } it 'does not raise' do expect { cleaner.start }.to_not raise_error end end describe 'DATABASE_CLEANER_ALLOW_REMOTE_DATABASE_URL is set' do let(:database_url) { 'postgres://remote.host' } before { stub_const('ENV', 'DATABASE_CLEANER_ALLOW_REMOTE_DATABASE_URL' => true) } it 'does not raise' do expect { cleaner.start }.to_not raise_error end end describe 'DatabaseCleaner.allow_remote_database_url is true' do let(:database_url) { 'postgres://remote.host' } before { DatabaseCleaner.allow_remote_database_url = true } after { DatabaseCleaner.allow_remote_database_url = nil } it 'does not raise' do expect { cleaner.start }.to_not raise_error end end end describe 'ENV is set to production' do %w(ENV RACK_ENV RAILS_ENV).each do |key| describe "on #{key}" do before { stub_const('ENV', key => "production") } it 'raises' do expect { cleaner.start }.to raise_error(Safeguard::Error::ProductionEnv) end end describe 'DATABASE_CLEANER_ALLOW_PRODUCTION is set' do before { stub_const('ENV', 'DATABASE_CLEANER_ALLOW_PRODUCTION' => true) } it 'does not raise' do expect { cleaner.start }.to_not raise_error end end describe 'DatabaseCleaner.allow_production is true' do before { DatabaseCleaner.allow_production = true } after { DatabaseCleaner.allow_production = nil } it 'does not raise' do expect { cleaner.start }.to_not raise_error end end end end end end database_cleaner-1.7.0/spec/database_cleaner/sequel/000077500000000000000000000000001326617530700224535ustar00rootroot00000000000000database_cleaner-1.7.0/spec/database_cleaner/sequel/base_spec.rb000066400000000000000000000014221326617530700247230ustar00rootroot00000000000000require 'spec_helper' require 'database_cleaner/sequel/base' require 'database_cleaner/shared_strategy' require 'sequel' module DatabaseCleaner describe Sequel do it { should respond_to(:available_strategies) } end module Sequel class ExampleStrategy include ::DatabaseCleaner::Sequel::Base end describe ExampleStrategy do it_should_behave_like "a generic strategy" it { should respond_to(:db) } it { should respond_to(:db=) } it "should store my desired db" do subject.db = :my_db subject.db.should eq :my_db end it "should default to :default" do pending "I figure out how to use Sequel and write some real tests for it..." subject.db.should eq :default end end end end database_cleaner-1.7.0/spec/database_cleaner/sequel/deletion_spec.rb000066400000000000000000000032171326617530700256200ustar00rootroot00000000000000require 'spec_helper' require 'database_cleaner/sequel/deletion' require 'database_cleaner/shared_strategy' require 'sequel' require 'support/active_record/database_setup' module DatabaseCleaner module Sequel describe Deletion do it_should_behave_like "a generic strategy" end shared_examples 'a Sequel deletion strategy' do let(:deletion) do d = Deletion.new d.db = db d end context 'when several tables have data' do before(:each) do db.create_table!(:precious_stones) { primary_key :id } db.create_table!(:replaceable_trifles) { primary_key :id } db.create_table!(:worthless_junk) { primary_key :id } db[:precious_stones].insert db[:replaceable_trifles].insert db[:worthless_junk].insert end context 'by default' do it 'deletes all the tables' do d = Deletion.new d.db = db d.clean expect(db[:replaceable_trifles]).to have(0).rows expect(db[:worthless_junk]).to have(0).rows expect(db[:precious_stones]).to have(0).rows end end end end supported_configurations = [ { :url => 'mysql:///', :connection_options => db_config['mysql'] }, { :url => 'postgres:///', :connection_options => db_config['postgres'] } ] supported_configurations.each do |config| describe "Sequel deletion (using a #{config[:url]} connection)" do let(:db) { ::Sequel.connect(config[:url], config[:connection_options]) } it_behaves_like 'a Sequel deletion strategy' end end end end database_cleaner-1.7.0/spec/database_cleaner/sequel/transaction_spec.rb000066400000000000000000000007371326617530700263460ustar00rootroot00000000000000require 'spec_helper' require 'database_cleaner/sequel/transaction' require 'database_cleaner/shared_strategy' require 'sequel' module DatabaseCleaner module Sequel describe Transaction do it_should_behave_like "a generic strategy" it_should_behave_like "a generic transaction strategy" describe "start" do it "should start a transaction" end describe "clean" do it "should finish a transaction" end end end end database_cleaner-1.7.0/spec/database_cleaner/sequel/truncation/000077500000000000000000000000001326617530700246415ustar00rootroot00000000000000database_cleaner-1.7.0/spec/database_cleaner/sequel/truncation/sqlite3_spec.rb000066400000000000000000000000001326617530700275520ustar00rootroot00000000000000database_cleaner-1.7.0/spec/database_cleaner/sequel/truncation_spec.rb000066400000000000000000000145031326617530700262030ustar00rootroot00000000000000require 'spec_helper' require 'database_cleaner/sequel/truncation' require 'database_cleaner/shared_strategy' require 'sequel' # XXX: use ActiveRecord's db_config (`db/config.yml`) for CI/dev convenience require 'support/active_record/database_setup' module DatabaseCleaner module Sequel describe Truncation do it_should_behave_like "a generic strategy" it_should_behave_like "a generic truncation strategy" end shared_examples 'a Sequel truncation strategy' do # XXX: it'd be really nice if Truncation accepted db: constructor parameter let(:truncation) do t = Truncation.new t.db = db t end context 'when several tables have data' do before(:each) do db.create_table!(:precious_stones) { primary_key :id } db.create_table!(:replaceable_trifles) { primary_key :id } db.create_table!(:worthless_junk) { primary_key :id } db[:precious_stones].insert db[:replaceable_trifles].insert db[:worthless_junk].insert end context 'by default' do it 'truncates all the tables' do t = Truncation.new t.db = db t.clean expect(db[:replaceable_trifles]).to have(0).rows expect(db[:worthless_junk]).to have(0).rows expect(db[:precious_stones]).to have(0).rows end end context 'when the Truncation is restricted to "only: [...]" some tables' do it 'truncates only the mentioned tables (and leaves the rest alone)' do t = Truncation.new(only: ['worthless_junk', 'replaceable_trifles']) t.db = db t.clean expect(db[:replaceable_trifles]).to have(0).rows expect(db[:worthless_junk]).to have(0).rows expect(db[:precious_stones]).to have(1).rows end end context 'when the Truncation is restricted to "except: [...]" some tables' do it 'leaves the mentioned tables alone (and truncates the rest)' do t = Truncation.new(except: ['precious_stones']) # XXX: Strings only, symbols are ignored t.db = db t.clean expect(db[:replaceable_trifles]).to be_empty expect(db[:worthless_junk]).to be_empty expect(db[:precious_stones]).to have(1).item end end end end shared_examples_for 'a truncation strategy without autoincrement resets' do it "leaves AUTO_INCREMENT index alone by default (BUG: it should be reset instead)" do # Jordan Hollinger made everything reset auto increment IDs # in commit 6a0104382647e5c06578aeac586c0333c8944492 so I'm pretty sure # everything is meant to reset by default. # # For Postgres, db[:mytable].truncate(restart: true) should work. # For SQLite, db[:sqlite_sequence].where(name: 'mytable').delete db.create_table!(:replaceable_trifles) { primary_key :id } table = db[:replaceable_trifles] 2.times { table.insert } truncation.clean id_after_clean = table.insert pending('the bug being fixed') do expect(id_after_clean).to eq 1 end end # XXX: it'd be really nice if Truncation accepted db: constructor parameter let(:truncation) do t = Truncation.new t.db = db t end end shared_examples_for 'a truncation strategy that resets autoincrement keys by default' do it "resets AUTO_INCREMENT primary keys" do db.create_table!(:replaceable_trifles) { primary_key :id } table = db[:replaceable_trifles] 2.times { table.insert } truncation.clean id_after_clean = table.insert expect(id_after_clean).to eq 1 end # XXX: it'd be really nice if Truncation accepted db: constructor parameter let(:truncation) do t = Truncation.new t.db = db t end end half_supported_configurations = [ {url: 'sqlite:///', connection_options: db_config['sqlite3']}, {url: 'postgres:///', connection_options: db_config['postgres']}, ] supported_configurations = [ {url: 'mysql:///', connection_options: db_config['mysql']}, {url: 'mysql2:///', connection_options: db_config['mysql2']} ] supported_configurations.each do |config| describe "Sequel truncation (using a #{config[:url]} connection)" do let(:db) { ::Sequel.connect(config[:url], config[:connection_options]) } it_behaves_like 'a Sequel truncation strategy' it_behaves_like 'a truncation strategy that resets autoincrement keys by default' describe '#pre_count?' do subject { Truncation.new.tap { |t| t.db = db } } its(:pre_count?) { should eq false } it 'should return true if @reset_id is set and non false or nil' do subject.instance_variable_set(:"@pre_count", true) subject.send(:pre_count?).should eq true end it 'should return false if @reset_id is set to false' do subject.instance_variable_set(:"@pre_count", false) subject.send(:pre_count?).should eq false end end describe "relying on #pre_count_truncate_tables if asked to" do subject { Truncation.new.tap { |t| t.db = db } } it "should rely on #pre_count_truncate_tables if #pre_count? returns true" do subject.instance_variable_set(:"@pre_count", true) subject.should_not_receive(:truncate_tables) subject.should_receive(:pre_count_truncate_tables) subject.clean end it "should not rely on #pre_count_truncate_tables if #pre_count? return false" do subject.instance_variable_set(:"@pre_count", false) subject.should_not_receive(:pre_count_truncate_tables) subject.should_receive(:truncate_tables) subject.clean end end end end half_supported_configurations.each do |config| describe "Sequel truncation (using a #{config[:url]} connection)" do let(:db) { ::Sequel.connect(config[:url], config[:connection_options]) } it_behaves_like 'a Sequel truncation strategy' it_behaves_like 'a truncation strategy without autoincrement resets' end end end end database_cleaner-1.7.0/spec/database_cleaner/shared_strategy.rb000066400000000000000000000006421326617530700246740ustar00rootroot00000000000000shared_examples_for "a generic strategy" do it { should respond_to(:db) } end shared_examples_for "a generic truncation strategy" do it { should respond_to(:start) } it { should respond_to(:clean) } it { should respond_to(:cleaning) } end shared_examples_for "a generic transaction strategy" do it { should respond_to(:start) } it { should respond_to(:clean) } it { should respond_to(:cleaning) } end database_cleaner-1.7.0/spec/rcov.opts000066400000000000000000000001141326617530700175740ustar00rootroot00000000000000--exclude "spec/*,vendor/*,examples/*,features/*,Users/*/.rvm/gems/*/gems/*"database_cleaner-1.7.0/spec/spec_helper.rb000066400000000000000000000004711326617530700205400ustar00rootroot00000000000000require "rubygems" require "bundler" Bundler.setup require 'rspec/core' require 'rspec/mocks' #require 'active_record' #require 'mongo_mapper' $:.unshift(File.dirname(__FILE__)) $:.unshift(File.dirname(__FILE__) + '/../lib') require 'database_cleaner' RSpec.configure do |config| end alias running lambda database_cleaner-1.7.0/spec/support/000077500000000000000000000000001326617530700174345ustar00rootroot00000000000000database_cleaner-1.7.0/spec/support/active_record/000077500000000000000000000000001326617530700222455ustar00rootroot00000000000000database_cleaner-1.7.0/spec/support/active_record/database_setup.rb000066400000000000000000000001631326617530700255560ustar00rootroot00000000000000require 'yaml' def db_config config_path = 'db/config.yml' @db_config ||= YAML.load(IO.read(config_path)) end database_cleaner-1.7.0/spec/support/active_record/migrations/000077500000000000000000000000001326617530700244215ustar00rootroot00000000000000database_cleaner-1.7.0/spec/support/active_record/migrations/20150101010000_create_users.rb000066400000000000000000000003241326617530700310430ustar00rootroot00000000000000class CreateUsers < ActiveRecord::Migration def self.up create_table :users do |t| t.string :name end end def self.down drop_table :users end end class ::User < ActiveRecord::Base end database_cleaner-1.7.0/spec/support/active_record/migrations/20150101020000_create_agents.rb000066400000000000000000000003301326617530700311610ustar00rootroot00000000000000class CreateAgents < ActiveRecord::Migration def self.up create_table :agents do |t| t.string :name end end def self.down drop_table :agents end end class ::Agent < ActiveRecord::Base end database_cleaner-1.7.0/spec/support/active_record/mysql2_setup.rb000066400000000000000000000016161326617530700252450ustar00rootroot00000000000000require 'support/active_record/database_setup' require 'support/active_record/schema_setup' module MySQL2Helper puts "Active Record #{ActiveRecord::VERSION::STRING}, mysql2" # require 'logger' # ActiveRecord::Base.logger = Logger.new(STDERR) def default_config db_config['mysql2'] end def create_db establish_connection(default_config.merge(:database => nil)) ActiveRecord::Base.connection.drop_database default_config['database'] rescue nil ActiveRecord::Base.connection.create_database default_config['database'] end def establish_connection(config = default_config) ActiveRecord::Base.establish_connection config end def active_record_mysql2_setup create_db establish_connection active_record_load_schema end def active_record_mysql2_connection ActiveRecord::Base.connection end end RSpec.configure do |c| c.include MySQL2Helper end database_cleaner-1.7.0/spec/support/active_record/mysql_setup.rb000066400000000000000000000016071326617530700251630ustar00rootroot00000000000000require 'support/active_record/database_setup' require 'support/active_record/schema_setup' module MySQLHelper puts "Active Record #{ActiveRecord::VERSION::STRING}, mysql" # require 'logger' # ActiveRecord::Base.logger = Logger.new(STDERR) def default_config db_config['mysql'] end def create_db establish_connection(default_config.merge(:database => nil)) ActiveRecord::Base.connection.drop_database default_config['database'] rescue nil ActiveRecord::Base.connection.create_database default_config['database'] end def establish_connection(config = default_config) ActiveRecord::Base.establish_connection config end def active_record_mysql_setup create_db establish_connection active_record_load_schema end def active_record_mysql_connection ActiveRecord::Base.connection end end RSpec.configure do |c| c.include MySQLHelper end database_cleaner-1.7.0/spec/support/active_record/postgresql_setup.rb000066400000000000000000000025231326617530700262170ustar00rootroot00000000000000require 'support/active_record/database_setup' require 'support/active_record/schema_setup' module PostgreSQLHelper puts "Active Record #{ActiveRecord::VERSION::STRING}, pg" # ActiveRecord::Base.logger = Logger.new(STDERR) def default_config db_config['postgres'] end def create_db @encoding = default_config['encoding'] || ENV['CHARSET'] || 'utf8' begin establish_connection(default_config.merge('database' => 'postgres', 'schema_search_path' => 'public')) ActiveRecord::Base.connection.drop_database(default_config['database']) rescue nil ActiveRecord::Base.connection.create_database(default_config['database'], default_config.merge('encoding' => @encoding)) rescue Exception => e $stderr.puts e, *(e.backtrace) $stderr.puts "Couldn't create database for #{default_config.inspect}" end end def establish_connection(config = default_config) ActiveRecord::Base.establish_connection(config) end def active_record_pg_setup create_db establish_connection active_record_load_schema end def active_record_pg_migrate create_db establish_connection ActiveRecord::Migrator.migrate 'spec/support/active_record/migrations' end def active_record_pg_connection ActiveRecord::Base.connection end end RSpec.configure do |c| c.include PostgreSQLHelper end database_cleaner-1.7.0/spec/support/active_record/schema_setup.rb000066400000000000000000000005021326617530700252470ustar00rootroot00000000000000def active_record_load_schema ActiveRecord::Schema.define do create_table :users, :force => true do |t| t.integer :name end create_table :agents, :id => false, :force => true do |t| t.integer :name end end end class ::User < ActiveRecord::Base end class ::Agent < ActiveRecord::Base end database_cleaner-1.7.0/spec/support/active_record/sqlite3_setup.rb000066400000000000000000000017521326617530700254030ustar00rootroot00000000000000require 'support/active_record/database_setup' require 'support/active_record/schema_setup' module SQLite3Helper puts "Active Record #{ActiveRecord::VERSION::STRING}, sqlite3" # ActiveRecord::Base.logger = Logger.new(STDERR) def default_config db_config['sqlite3'] end def create_db @encoding = default_config['encoding'] || ENV['CHARSET'] || 'utf8' begin establish_connection(default_config.merge('database' => 'sqlite3', 'schema_search_path' => 'public')) rescue Exception => e $stderr.puts e, *(e.backtrace) $stderr.puts "Couldn't create database for #{default_config.inspect}" end end def establish_connection(config = default_config) ActiveRecord::Base.establish_connection(config) end def active_record_sqlite3_setup create_db establish_connection active_record_load_schema end def active_record_sqlite3_connection ActiveRecord::Base.connection end end RSpec.configure do |c| c.include SQLite3Helper end database_cleaner-1.7.0/spec/support/data_mapper/000077500000000000000000000000001326617530700217115ustar00rootroot00000000000000database_cleaner-1.7.0/spec/support/data_mapper/schema_setup.rb000066400000000000000000000003451326617530700247200ustar00rootroot00000000000000def data_mapper_load_schema require 'dm-migrations' DataMapper.auto_migrate! end class ::DmUser include DataMapper::Resource self.storage_names[:default] = 'users' property :id, Serial property :name, String end database_cleaner-1.7.0/spec/support/data_mapper/sqlite3_setup.rb000066400000000000000000000016521326617530700250460ustar00rootroot00000000000000require 'support/active_record/database_setup' require 'support/data_mapper/schema_setup' module DataMapperSQLite3Helper puts "DataMapper #{DataMapper::VERSION}, sqlite3" def default_config db_config['sqlite3'] end def create_db @encoding = default_config['encoding'] || ENV['CHARSET'] || 'utf8' begin establish_connection(default_config.merge('database' => 'sqlite3', 'schema_search_path' => 'public')) rescue Exception => e $stderr.puts e, *(e.backtrace) $stderr.puts "Couldn't create database for #{default_config.inspect}" end end def establish_connection(config = default_config) DataMapper.setup(:default, config) end def data_mapper_sqlite3_setup create_db establish_connection data_mapper_load_schema end def data_mapper_sqlite3_connection DataMapper.repository.adapter end end RSpec.configure do |c| c.include(DataMapperSQLite3Helper) end