How to drop your Postgres database with Rails 4

Update September 28 2016: There is now a gem that you can include in your app to use the technique detailed below.

When you use Postgres as your database with Rails and try to drop your database using rake db:drop, you might run into this annoying error:

PG::ObjectInUse: ERROR:  database "myapp_development" is being accessed by other users
DETAIL:  There is 1 other session using the database.
: DROP DATABASE IF EXISTS "myapp_development"

The problem is that Postgres won't drop the database if there are other sessions using it. The solution is, as you might have guessed, to stop all other sessions first and then drop the database. This can be easily implemented by monkeypatching the code responsible for dropping the database.

If you're using Rails 3.x, use the code mentioned here.

If you're on Rails 4.x, use this: (see notes below)

# config/initializers/postgresql_database_tasks.rb
module ActiveRecord
  module Tasks
    class PostgreSQLDatabaseTasks
      def drop
        connection.select_all "select pg_terminate_backend( from pg_stat_activity where datname='#{configuration['database']}' AND state='idle';"
        connection.drop_database configuration['database']

Note 1: You need to run the db:drop Rake task with the environment option so the initializer is picked up: rake environment db:drop

Note 2: As pointed out in the comments, the column was called pg_stat_activity.procpid in Postgres < 9.2. Make sure to replace it if you're working with an older version of Postgres.

Discuss this post on Hacker News

Ideas? Constructive criticism? Think I'm stupid? Let me know in the comments!