Skip to content

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.

If you are using PlanetScale with a Rails application, go to your database's Settings page in the web app and enable "Automatically copy migration data." Select "Rails/Phoenix" as the migration framework. 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.

Automatic schema migrations work with any migration tool, not just Rails. Specify the migration table name in your database's Settings page.

Quick introduction 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.
When you merge a deploy request in PlanetScale, the schema_migrations table in main gets automatically updated with the migrations from your branch.

Prerequisites

Copied
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:
Copied
pscale branch create blog add-users-table
  1. Switch to your newly created development branch, add-users-table:
Copied
pscale branch switch add-users-table --database blog
  1. Create a Rails migration and call it CreateUsers:
Copied
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:
Copied
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:
Copied
pscale branch create blog add-index-to-users

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

  1. Switch to your newly created development branch, add-index-to-users:
Copied
pscale branch switch add-index-to-users --database blog
  1. Create another Rails migration for your table and call it CreateUsersIndex:
Copied
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:
Copied
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.

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?

Learn more about how PlanetScale allows you to make non-blocking schema changes to your database tables, without locking or causing downtime for production databases.

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 October 20, 2021
Help us improve this page
PrivacyTerms© 2021 PlanetScale Inc.