Recently, we set up a new Rails project (named as
app below), and our
database.yml is shown below, so you can see that it reads from environment variables to set database names and credentials accordingly:
default: &default adapter: postgresql encoding: unicode pool: <%= ENV['DATABASE_POOL'] %> host: <%= ENV['DATABASE_HOST'] %> database: <%= ENV['DATABASE_NAME'] %> username: <%= ENV['DATABASE_USER'] %> password: <%= ENV['DATABASE_PASSWORD'] %> development: <<: *default test: <<: *default
we noticed that rake DB tasks always run twice in development environment as shown below:
$ rake db:drop Dropped database 'app_development' Dropped database 'app_development' $ rake db:create Created database 'app_development' app_development already exists
After I drill down the problem, I found that the problem is caused by a 'smart' feature in Rails. When running DB rake tasks, ActiveRecord checks the current environment, and if current environment is development, it runs the task in development database first and followed by test database (you can refer to method
lib/activerecord/tasks/database_tasks.rb for more details).
database.yml relies on environment variables to determine the target database. When a rake DB task is executed in development environment, the task will be run upon development database first, which is
app_development. Then, the task is run upon test database, which is
app_development again, because the environment variables for databases are the same. That is why the same task is run twice on development database.
To fix this, I simply hard code the database name for test environment in database.yml:
test: <<: *default database: knight_test