title: Rake db:test:prepare task deleting data in development database
body: <p>Using a <a href="https://github.com/mhartl/sample_app_rails_3_2/blob/master/config/database.yml" rel="nofollow noreferrer">simple Rails sqlite3 configuration example</a> in my <strong>config/database.yml</strong> for a Rails 3.2.6 app, I used to reset my development database, re-seed it, and prepare my test database simply by performing:</p>
  <pre><code>$ rake db:reset
  $ rake db:test:prepare 
  </code></pre>
  <p>After looking at <a href="https://web.archive.org/web/20120924203633/http://matthew.mceachen.us:80/blog/howto-test-your-rails-application-with-travis-ci-on-different-database-engines-1220.html" rel="nofollow noreferrer">this blog entry</a> about testing a Rails application with <a href="https://travis-ci.org/" rel="nofollow noreferrer">Travis CI</a> on different database engines, I thought I'd give it a try, so I installed mysql and postgresql using <a href="https://brew.sh/" rel="nofollow noreferrer">Homebrew</a> (I'm on OSX Snow Leopard), set them up as per the <code>brew info</code> instructions.  I installed the relevant gems, and configured the database and Travis files as follows:</p>
  <p><strong>Gemfile</strong></p>
  <pre><code># ...
  group :development, :test do
    # ...
    gem 'sqlite3', '1.3.6'
  end
  
  group :test do
    # ...
    # Test mysql on Travis CI
    gem 'mysql2', '0.3.11'
  end
  
  group :test, :production do
    # ...
    # Test postgres on Travis CI and deploy on Heroku
    gem 'pg', '0.13.2'
  end
  </code></pre>
  <p><strong>config/database.yml</strong></p>
  <pre><code>sqlite: &amp;sqlite
    adapter: sqlite3
    database: db/&lt;%= Rails.env %&gt;.sqlite3
  
  mysql: &amp;mysql
    adapter: mysql2
    username: root
    password:
    database: my_app_&lt;%= Rails.env %&gt;
  
  postgresql: &amp;postgresql
    adapter: postgresql
    username: postgres
    password:
    database: my_app_&lt;%= Rails.env %&gt;
    min_messages: ERROR
  
  defaults: &amp;defaults
    pool: 5
    timeout: 5000
    host: localhost
    &lt;&lt;: *&lt;%= ENV['DB'] || &quot;sqlite&quot; %&gt;
  
  development:
    &lt;&lt;: *defaults
  
  test: &amp;test
    &lt;&lt;: *defaults
  
  production:
    &lt;&lt;: *defaults
  
  cucumber:
    &lt;&lt;: *test
  </code></pre>
  <p><strong>.travis.yml</strong></p>
  <pre><code>language: ruby
  rvm:
    - 1.9.2
    - 1.9.3
  env:
    - DB=sqlite
    - DB=mysql
    - DB=postgresql
  script:
    - RAILS_ENV=test bundle exec rake --trace db:migrate
    - bundle exec rake db:test:prepare
    - bundle exec rspec spec/
  before_script:
    - mysql -e 'create database my_app_test'
    - psql -c 'create database my_app_test' -U postgres
  bundler_args: --binstubs=./bundler_stubs
  </code></pre>
  <p>Now, though, when I run <code>rake db:reset</code>, I get a <code>Couldn't drop db/development.sqlite3</code> error message before the development database is successfully created.  So, it seems that there are now multiple calls being made to drop the same database(?).  The traced output looks like:</p>
  <pre><code>$ rake db:reset --trace
  ** Invoke db:reset (first_time)
  ** Invoke environment (first_time)
  ** Execute environment
  ** Execute db:reset
  ** Invoke db:drop (first_time)
  ** Invoke db:load_config (first_time)
  ** Invoke rails_env (first_time)
  ** Execute rails_env
  ** Execute db:load_config
  ** Execute db:drop
  Couldn't drop db/development.sqlite3 : #&lt;Errno::ENOENT: No such file or directory - my_app/db/development.sqlite3&gt;
  ** Invoke db:setup (first_time)
  ** Invoke db:schema:load_if_ruby (first_time)
  ** Invoke db:create (first_time)
  ** Invoke db:load_config 
  ** Execute db:create
  db/development.sqlite3 already exists
  # ...
  </code></pre>
  <p>This is odd, but at least the development database gets created and seeded.  The real issue comes when I run <code>rake db:test:prepare</code>: although there are no error messages, as well as the test database not being created, the data in the development database gets blown away (schema is still in tact, though).  I tried directly specifying the Rails environment for the command and got:</p>
  <pre><code>$ rake db:test:prepare RAILS_ENV=test
  You have 7 pending migrations:
  20120503193649 CreateUsers
  # ...
  Run `rake db:migrate` to update your database then try again.
  </code></pre>
  <p>After running <code>rake db:migrate RAILS_ENV=test</code>, I could run my rspec tests again.  So, my rake commands to get the same results have now changed to:</p>
  <pre><code>$ rake db:reset # (with an error)
  $ rake db:migrate RAILS_ENV=test
  </code></pre>
  <p><em>If I change my</em> <strong>config/database.yml</strong> <em>file back to a simple sqlite3 only configuration,</em> <code>db:reset</code> <em>and</em> <code>db:test:prepare</code> <em>work as I expect.</em></p>
  <p>So, does this mean that my mysql and/or postgres settings are causing rake tasks to repeat and/or they're messing with the Rails environment settings?  Where should I be looking to confirm if my environment is really set up to work properly with these 3 database engines?</p>
  <h3>Edit</h3>
  <p>Looking at the <a href="https://weblog.rubyonrails.org/2012/8/3/ann-rails-3-2-8-rc2-has-been-released/" rel="nofollow noreferrer">release notes for Rails 3.2.8.rc2</a>, I found a change to <code>ActiveRecord</code> potentially related to this question:</p>
  <ul>
  <li>Do not set <code>RAILS_ENV</code> to <code>development</code> when using <code>db:test:prepare</code> and related rake tasks. This was causing the truncation of the development database data when using RSpec. In RC2 was fixed again when using <code>config.active_record.schema_format = :sql</code></li>
  </ul>
  <p><strong>config/application.rb</strong> has the following explanation:</p>
  <pre><code># Use SQL instead of Active Record's schema dumper when creating the database.
  # This is necessary if your schema can't be completely dumped by the schema dumper,
  # like if you have constraints or database-specific column types
  # config.active_record.schema_format = :sql
  </code></pre>
  <p>My schema doesn't have constraints or database-specific column types, so I didn't uncomment this line, however, given the content of the release note, I wagered that <code>RAILS_ENV</code> defaulting to <code>development</code> could be responsible for the deleted data in the development environment.  So, I tried out a few things and got expected results by doing what I did before (after upgrading Rails to 3.2.8.rc2):</p>
  <pre><code>$ rake db:reset # (with an error)
  $ rake db:test:prepare RAILS_ENV=test # (with no &quot;pending migrations&quot; issue)
  </code></pre>
  <p>This is a bit better, but still seems wrong to me since there is still an error with <code>rake db:reset</code>, and it doesn't make sense to me to have to set <code>RAILS_ENV=test</code> when running a rake command specifically tailored for the test database.</p>
  <h2>Update</h2>
  <p>It would seem that upgrading to Rails 3.2.9 solves this issue due to the following fix:</p>
  <ul>
  <li>Fix bug where <code>rake db:test:prepare</code> tries to load the structure.sql into development database. Fixes #8032.</li>
  </ul>
  <p><em>Grace Liu + Rafael Mendonça França</em></p>
  <p>I can now again reset my development database, re-seed it, and prepare my test database simply by performing:</p>
  <pre><code>$ rake db:reset
  $ rake db:test:prepare 
  </code></pre>