Rails 6 adds db:prepare rake task

Working across teams, we always need to keep the database in sync with code changes, with migrations across branches and more.

To sync up, or when setting up a new database, we run the following commands:

# Create Database
rails db:create 
# Populate Seed Data
rails db:seed  
# Sync up migrations on current branch
rails db:migrate

Rails 6 adds rake db:prepare to take care of the above for us, and prepare the database for use of the required database.

Problems with just migrate

Running rails db:migrate when the database doesnt exist, throws ActiveRecord::NoDatabaseError.

  blog git:(master)  rails db:migrate
rails aborted!
ActiveRecord::NoDatabaseError: FATAL:  database "blog_development" does not exist

The task db:prepare internally catches ActiveRecord::NoDatabaseError and then runs rails db:setup.

In other words, if the database is correctly configured, db:prepare will just run the migration, if the database already exists. If the database does not exist, db:prepare ensures that it is created, migrated and seeded with data.

Behaviour depending on presence of database

When database is present:

  blog git:(master)  rails db:prepare
== 20190513112934 CreateArticles: migrating ===================================
-- create_table(:articles)
   -> 0.0103s
== 20190513112934 CreateArticles: migrated (0.0104s) ==========================

This executed migrations on the existing database.

When database is not present:

  blog git:(master)  rails db:prepare
Created database 'blog_development'

This created the database and populated seed data.

Important bit is that db:prepare always runs in an idempotent way. This is useful when being utilized in CI scripts, staging deployments, and more.