Rake db:test:prepare task deleting data in development database

江枫思渺然 提交于 2019-12-03 05:49:58

Your development database is being purged because ActiveRecord::Base.configurations has the test database set to "development.sqlite3". When the rake task is run, the yaml configuration is eval'ed into the ActiveRecord::Base.configurations hash and at that time Rails.env is set to development.

If RAILS_ENV=development, the database value for test will be set to

database: db/development.sqlite3

or for a different adapter:

database: my_app_development

You can reproduce this with a simple sqlite only configuration buy changing the test block inside database.yml to the following:

test:
  adapter: sqlite3
  database: db/<%= Rails.env %>.sqlite3
  pool: 5
  timeout: 5000

If you inspect the full ActiveRecord::Base.configurations hash you'll see that test is set to use the development db if no RAILS_ENV is specified. And if you were to specify 'production' or 'staging' it would be set to that. From the console:

# rails c
> ActiveRecord::Base.configurations['test']['database']
  => "db/development.sqlite3" 

compared with:

# RAILS_ENV=test rails c
> ActiveRecord::Base.configurations['test']['database']
  => "db/test.sqlite3"

Update

The issue you are seeing with db:reset is also because your yaml file is interpreted once and then the config is set.

db:reset will invoke db:drop and db:setup for the given environment. However, if the environment is development, it also does those tasks for the test environment. So it succeeds in dropping for the development environment and then when it executes for test, the database key of the configuration is identical to the development section, hence it can't drop something that no longer exists. Here is what the ActiveRecord::Base.configurations hash looks like when Rails.env == 'development'

"development" => {
    "adapter" => "sqlite3",
    "database" => "db/development.sqlite3", 
    "pool" => 5, 
    "timeout" => 5000
}, 
"test" => {
    "adapter" => "sqlite3", 
    "database" => "db/development.sqlite3",
    "pool" =>5, 
    "timeout"=>5000
}, 
"production" => {
    "adapter" => "sqlite3", 
    "database" => "db/development.sqlite3",
    "pool"=>5, 
    "timeout"=>5000
}

And once it's in that hash, it doesn't go back and re-read the database.yml file. That hash is what is generated given this database.yml

development:
  adapter: sqlite3
  database: db/<%= Rails.env %>.sqlite3
  pool: 5
  timeout: 5000

test:
  adapter: sqlite3
  database: db/<%= Rails.env %>.sqlite3
  pool: 5
  timeout: 5000

production:
  adapter: sqlite3
  database: db/<%= Rails.env %>.sqlite3
  pool: 5
  timeout: 5000

Same problem i.e. development database destroyed after a "rake".

My way out "rake RAILS_ENV=test".

Using ruby 1.9.3p194 Rails 3.2.7 sqlite3.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!