Automatic Rails Migrations

To ensure PlanetScale works well with a traditional Rails development process, we implemented the ability to automatically copy Rails migration metadata as part of our deployment process.
Tip: If you are using PlanetScale with a Rails application, go into the web UI and enable "Automatic Rails Migrations" in your database settings page. When enabled, this setting updates the schema_migrations table each time you branch with the latest migration. If disabled, running rake db:migrate will try to run all migrations every time, instead of only the latest one.

Introduction

In this tutorial, we’re going to learn how to run automatic Rails migrations in PlanetScale as part of our deployment process.

Quick Intro to Rails Migrations

Rails tracks the list of schema migrations run with an internal table called schema_migrations in your database. These migrations are executed when running the Rails command rake db:migrate.

From a high level, running rake db:migrate does the following:

  • Rails looks at all of the migration files in your db/migrate directory
  • Rails runs a query against the schema_migrations table to see which migrations have and haven't been run.
  • Any migration that doesn’t appear in the schema_migrations table is considered pending, and is executed against the database with the schema changes in the file.
Tip: When you merge a deploy request in PlanetScale, the schema_migrations table in main gets automatically updated with the migrations from your branch.

Prerequisites

$pscale auth login

Execute first Rails Migration in PlanetScale

Rails migrations follow the PlanetScale non-blocking schema change workflow. First, the migration is applied to a development branch and then the development branch is merged into the main production database.

Let's begin with an example flow for running Rails migrations in PlanetScale:

  1. Create an add-users-table development branch from main and name your database blog:
$pscale branch create blog add-users-table
  1. Switch to your newly created development branch, add-users-table:
$pscale branch switch add-users-table --database blog
  1. Create a Rails migration and call it CreateUsers:
$rails generate migration CreateUsers

This rails command begins the migration for our table that is currently empty and generates a Ruby file that’ll be named something like this: 20200405103635_create_users.rb.

  1. We can fill in the body of this skeleton file with a few more relevant details, such as a user's name and email:
class CreateUsers < ActiveRecord::Migration[6.1]
def change
create_table :users do |t|
t.string :name
t.string :email
t.timestamps
end
end
end
  1. Run rake db:migrate.

This command executes a new migration against your add-users-table development branch.

At this point, Rails creates the users table and inserts 20200405103635 into the schema_migrations table on your development branch.

  1. Open a deploy request for your add-users-table branch, so that you can deploy your changes to main.

This step creates the users table in production. At this point, PlanetScale inserts 20200405103635 into main’s schema_migrations table.

Execute succeeding Rails Migrations in PlanetScale

Our first example migration flow went well, but what happens when you need to run further migrations?

Let’s take a look:

  1. Create an add-index-to-users new development branch from main:
$pscale branch create blog add-index-to-users

As part of creating that branch, PlanetScale copies every piece of data from main’s schema_migrations table over to your new development branch.

  1. Switch to your newly created development branch, add-index-to-users:
$pscale branch switch add-index-to-users --database blog
  1. Create another Rails migration for your table and call it CreateUsersIndex:
$rails generate migration CreateUsersIndex

This rails command begins the migration for our table that is currently empty and generates a Ruby file that’ll be named something like this: 20300405103635_create_users_index.rb.

  1. We fill in the body of the skeleton file with an index on the user table's email column:
class CreateUsersIndex < ActiveRecord::Migration[6.1]
def change
add_index(:users, :email, unique: true)
end
end
  1. Run rake db:migrate against your new development branch.

Rails queries schema_migrations to ensure your create_users migration already ran and proceeds to only run your new migration.

  1. Open a deploy request for your add-index-to-users branch, so that you can deploy these changes to main.

You did it! You successfully ran automatic Rails migrations in PlanetScale.

A note: Support for other frameworks is coming soon!

Summary

In this tutorial, we learned how to conduct our first automatic Rails migration in PlanetScale, as part of the deployment process. We also covered how to manage future migrations, so that all migration workflows can run seamlessly within the PlanetScale branching workflow.

What's next?

Now that you've successfully conducted your first automatic Rails migration in PlanetScale and know how to handle future migrations, it's time to deploy your application with a PlanetScale database! Let's learn how to deploy an application with a PlanetScale database to Heroku. You can even use this same Rails application that's already running locally for that tutorial.

Need help?

Get help from PlanetScale's support team, or join our GitHub Discussion board to see how others are using PlanetScale.

Was this page useful?
Last updated on June 16, 2021
PrivacyTerms
© 2021 PlanetScale Inc.