> ## Documentation Index
> Fetch the complete documentation index at: https://planetscale.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Connect a Rails application to PlanetScale

export const PlatformAvailability = ({current, vitess, postgres}) => {
  const docsHref = path => {
    if (!path) return path;
    const normalized = path.startsWith('/') ? path : `/${path}`;
    return normalized;
  };
  const labels = {
    vitess: 'Vitess',
    postgres: 'Postgres'
  };
  if (current === 'both') {
    return <div className="not-prose mb-5 flex flex-wrap items-center gap-2" role="group" aria-label="Platform availability">
        <span data-engine="both" data-state="current" aria-current="true" className="inline-flex items-center gap-1.5 whitespace-nowrap rounded-full border px-2.5 py-1 text-[13px] font-semibold leading-tight no-underline data-[engine=vitess]:data-[state=current]:border-[#ffc59b] data-[engine=vitess]:data-[state=current]:bg-[#ffe8d8] data-[engine=vitess]:data-[state=current]:text-[#672002] dark:data-[engine=vitess]:data-[state=current]:border-[#962d00] dark:data-[engine=vitess]:data-[state=current]:bg-[#3c1403] dark:data-[engine=vitess]:data-[state=current]:text-[#ffe8d8] data-[engine=vitess]:data-[state=link]:border-[#ffc59b] data-[engine=vitess]:data-[state=link]:bg-transparent data-[engine=vitess]:data-[state=link]:text-[#b83a05] dark:data-[engine=vitess]:data-[state=link]:border-[#962d00] dark:data-[engine=vitess]:data-[state=link]:bg-transparent dark:data-[engine=vitess]:data-[state=link]:text-[#ffc59b] data-[engine=postgres]:data-[state=current]:border-[#a9dffe] data-[engine=postgres]:data-[state=current]:bg-[#ddf2ff] data-[engine=postgres]:data-[state=current]:text-[#0e3682] dark:data-[engine=postgres]:data-[state=current]:border-[#144eb6] dark:data-[engine=postgres]:data-[state=current]:bg-[#08204e] dark:data-[engine=postgres]:data-[state=current]:text-[#ddf2ff] data-[engine=postgres]:data-[state=link]:border-[#a9dffe] data-[engine=postgres]:data-[state=link]:bg-transparent data-[engine=postgres]:data-[state=link]:text-[#0b6ec5] dark:data-[engine=postgres]:data-[state=link]:border-[#144eb6] dark:data-[engine=postgres]:data-[state=link]:bg-transparent dark:data-[engine=postgres]:data-[state=link]:text-[#73c7f9] data-[engine=both]:data-[state=current]:border-[#d4d4d4] data-[engine=both]:data-[state=current]:bg-[#f0f0f0] data-[engine=both]:data-[state=current]:text-[#3d3d3d] dark:data-[engine=both]:data-[state=current]:border-[#525252] dark:data-[engine=both]:data-[state=current]:bg-[#2a2a2a] dark:data-[engine=both]:data-[state=current]:text-[#e5e5e5]">
          Vitess and Postgres
        </span>
      </div>;
  }
  const hasVitess = current === 'vitess' || Boolean(vitess);
  const hasPostgres = current === 'postgres' || Boolean(postgres);
  const only = !(hasVitess && hasPostgres);
  const engines = [];
  if (current === 'vitess' || current === 'postgres') engines.push(current);
  if (hasVitess && current !== 'vitess') engines.push('vitess');
  if (hasPostgres && current !== 'postgres') engines.push('postgres');
  return <div className="not-prose mb-5 flex flex-wrap items-center gap-2" role="group" aria-label="Platform availability">
      {engines.map(engine => {
    const isCurrent = current === engine;
    const href = docsHref(engine === 'vitess' ? vitess : postgres);
    const label = only ? `${labels[engine]} only` : labels[engine];
    const state = isCurrent || !href ? 'current' : 'link';
    if (isCurrent || !href) {
      return <span key={engine} data-engine={engine} data-state={state} aria-current={isCurrent ? 'true' : undefined} className="inline-flex items-center gap-1.5 whitespace-nowrap rounded-full border px-2.5 py-1 text-[13px] font-semibold leading-tight no-underline data-[engine=vitess]:data-[state=current]:border-[#ffc59b] data-[engine=vitess]:data-[state=current]:bg-[#ffe8d8] data-[engine=vitess]:data-[state=current]:text-[#672002] dark:data-[engine=vitess]:data-[state=current]:border-[#962d00] dark:data-[engine=vitess]:data-[state=current]:bg-[#3c1403] dark:data-[engine=vitess]:data-[state=current]:text-[#ffe8d8] data-[engine=vitess]:data-[state=link]:border-[#ffc59b] data-[engine=vitess]:data-[state=link]:bg-transparent data-[engine=vitess]:data-[state=link]:text-[#b83a05] dark:data-[engine=vitess]:data-[state=link]:border-[#962d00] dark:data-[engine=vitess]:data-[state=link]:bg-transparent dark:data-[engine=vitess]:data-[state=link]:text-[#ffc59b] data-[engine=postgres]:data-[state=current]:border-[#a9dffe] data-[engine=postgres]:data-[state=current]:bg-[#ddf2ff] data-[engine=postgres]:data-[state=current]:text-[#0e3682] dark:data-[engine=postgres]:data-[state=current]:border-[#144eb6] dark:data-[engine=postgres]:data-[state=current]:bg-[#08204e] dark:data-[engine=postgres]:data-[state=current]:text-[#ddf2ff] data-[engine=postgres]:data-[state=link]:border-[#a9dffe] data-[engine=postgres]:data-[state=link]:bg-transparent data-[engine=postgres]:data-[state=link]:text-[#0b6ec5] dark:data-[engine=postgres]:data-[state=link]:border-[#144eb6] dark:data-[engine=postgres]:data-[state=link]:bg-transparent dark:data-[engine=postgres]:data-[state=link]:text-[#73c7f9] data-[engine=both]:data-[state=current]:border-[#d4d4d4] data-[engine=both]:data-[state=current]:bg-[#f0f0f0] data-[engine=both]:data-[state=current]:text-[#3d3d3d] dark:data-[engine=both]:data-[state=current]:border-[#525252] dark:data-[engine=both]:data-[state=current]:bg-[#2a2a2a] dark:data-[engine=both]:data-[state=current]:text-[#e5e5e5]">
              {label}
            </span>;
    }
    return <a key={engine} href={href} data-engine={engine} data-state={state} title={`View ${labels[engine]} documentation`} className="inline-flex items-center gap-1.5 whitespace-nowrap rounded-full border px-2.5 py-1 text-[13px] font-semibold leading-tight no-underline data-[engine=vitess]:data-[state=current]:border-[#ffc59b] data-[engine=vitess]:data-[state=current]:bg-[#ffe8d8] data-[engine=vitess]:data-[state=current]:text-[#672002] dark:data-[engine=vitess]:data-[state=current]:border-[#962d00] dark:data-[engine=vitess]:data-[state=current]:bg-[#3c1403] dark:data-[engine=vitess]:data-[state=current]:text-[#ffe8d8] data-[engine=vitess]:data-[state=link]:border-[#ffc59b] data-[engine=vitess]:data-[state=link]:bg-transparent data-[engine=vitess]:data-[state=link]:text-[#b83a05] dark:data-[engine=vitess]:data-[state=link]:border-[#962d00] dark:data-[engine=vitess]:data-[state=link]:bg-transparent dark:data-[engine=vitess]:data-[state=link]:text-[#ffc59b] data-[engine=postgres]:data-[state=current]:border-[#a9dffe] data-[engine=postgres]:data-[state=current]:bg-[#ddf2ff] data-[engine=postgres]:data-[state=current]:text-[#0e3682] dark:data-[engine=postgres]:data-[state=current]:border-[#144eb6] dark:data-[engine=postgres]:data-[state=current]:bg-[#08204e] dark:data-[engine=postgres]:data-[state=current]:text-[#ddf2ff] data-[engine=postgres]:data-[state=link]:border-[#a9dffe] data-[engine=postgres]:data-[state=link]:bg-transparent data-[engine=postgres]:data-[state=link]:text-[#0b6ec5] dark:data-[engine=postgres]:data-[state=link]:border-[#144eb6] dark:data-[engine=postgres]:data-[state=link]:bg-transparent dark:data-[engine=postgres]:data-[state=link]:text-[#73c7f9] data-[engine=both]:data-[state=current]:border-[#d4d4d4] data-[engine=both]:data-[state=current]:bg-[#f0f0f0] data-[engine=both]:data-[state=current]:text-[#3d3d3d] dark:data-[engine=both]:data-[state=current]:border-[#525252] dark:data-[engine=both]:data-[state=current]:bg-[#2a2a2a] dark:data-[engine=both]:data-[state=current]:text-[#e5e5e5]">
            {label}
            <svg aria-hidden="true" width="12" height="12" viewBox="0 0 12 12" fill="none" className="shrink-0">
              <path d="M2.5 6h7M6.5 3l3 3-3 3" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
            </svg>
          </a>;
  })}
    </div>;
};

<PlatformAvailability current="vitess" postgres="/postgres/tutorials/planetscale-postgres-rails" />

## Introduction

In this tutorial, you’re going to create a simple Rails application named *blog* and connect it to a PlanetScale database. You’ll perform the initial migration from your local Rails application, and set up the database for future development.

<Tip>
  Already have a Rails application and just want to connect to PlanetScale? Check out the [Rails quick connect repo](https://github.com/planetscale/connection-examples/tree/main/ruby).
</Tip>

## Prerequisites

* Install [Ruby and the Rails gem](https://guides.rubyonrails.org/getting_started.html#creating-a-new-rails-project-installing-rails).
* Install the [PlanetScale CLI](https://github.com/planetscale/cli).
* Authenticate the CLI with the following command:

```bash theme={null}
pscale auth login
```

## Create a Rails project

To connect a Rails application to a PlanetScale database, you'll first create a sample Rails project named *blog* and install the libraries needed to connect to your PlanetScale database.

Open the command line and follow these steps:

<Steps>
  <Step>
    Create a Rails app named *blog* by running the following command:

    ```bash theme={null}
    rails new blog
    ```
  </Step>

  <Step>
    Change into the directory you just created, the `blog` Rails app:

    ```bash theme={null}
    cd blog
    ```
  </Step>

  <Step>
    Next, add the `trilogy` gem to your *Gemfile*:

    ```ruby theme={null}
    gem "trilogy"
    ```
  </Step>

  <Step>
    Then run `bundle install`

    At this point, you have accomplished two things: you've created a Rails project called *blog* and installed the libraries that you'll need to connect to your PlanetScale database. Now, it’s time to create a PlanetScale database.
  </Step>
</Steps>

## Create a PlanetScale database and password

Now you'll need to create credentials for your Rails application to use.

### Using the CLI to create a connection string

<Steps>
  <Step>
    Using the `pscale` CLI, create a new database also named *blog*:

    ```bash theme={null}
    pscale database create blog
    ```
  </Step>

  <Step>
    Using the `pscale` CLI, create a new database password for the `main` branch of your database named *blog*:

    ```bash theme={null}
    pscale password create blog main <PASSWORD_NAME>
    ```

    <Note>
      The `PASSWORD_NAME` value represents the name of the username and password being generated. You can have multiple credentials for a branch, so this gives you a way to categorize them. To manage your passwords in the dashboard, go to your database dashboard page, click "Settings", and then click "Passwords".
    </Note>
  </Step>

  <Step>
    Take note of the values returned to you, as they will not be shown again.

    ```
      NAME                  BRANCH   USERNAME       ACCESS HOST URL                     ROLE     ROLE DESCRIPTION   PASSWORD
     --------------------- -------- -------------- ----------------------------------- -------- ------------------ -------------------------------------------------------
      development-password  main     xxxxxxxx   xxxxxxxxxx.us-east-3.psdb.cloud   writer   Can Read & Write   pscale_pw_xxxxxxxxxxxxxxxxxxxxx
    ```
  </Step>
</Steps>

<Note>
  You can also create passwords in the PlanetScale dashboard, as documented [in our Creating a password documentation](/docs/vitess/connecting/connection-strings#creating-a-password).
</Note>

## Configure Rails and PlanetScale

Let's set up the Rails application to talk to the new database.

Open `config/database.yml` and configure the `development` database settings with your new credentials from the output in the previous step:

```yaml theme={null}
development:
  <<: *default
  adapter: trilogy
  database: blog
  username: <USERNAME>
  host: <ACCESS HOST URL>
  password: <PASSWORD>
  ssl_mode: <%= Trilogy::SSL_VERIFY_IDENTITY %>
```

For `database` (database name), you can use your PlanetScale database name directly if you have a *single unsharded keyspace*. If you have a sharded keyspace, you'll need to use `@primary`. This will automatically direct incoming queries to the correct keyspace/shard. For more information, see the [Targeting the correct keyspace documentation](/docs/vitess/sharding/targeting-correct-keyspace).

The correct `sslca` path depends on your operating system and distribution. See [CA root configuration](/docs/vitess/connecting/secure-connections#ca-root-configuration) for more information.

<Note>
  You're configuring the **development** Rails environment here for the sake of expedience. In actual use, the **main** database branch would typically serve the **production** environment.
</Note>

Because this is a Rails app, you can also enable [Automatic Rails migrations](/docs/vitess/tutorials/automatic-rails-migrations) from the database's settings page. Select your database, click on the `main` branch, click "**Settings**", check the "**Automatically copy migration data**" box, and select "**Rails**" from the dropdown.

## Migrate your database

Here comes the fun stuff! Now that your application is configured to talk to PlanetScale, you can create your first migration.

<Steps>
  <Step>
    Create a Rails migration and call it `CreateUsers`:

    ```bash theme={null}
    rails generate migration CreateUsers
    ```

    This rails command begins the migration for your table that is currently empty and generates a Ruby file that’ll be named something like this:
    `db/migrate/20211014210422_create_users.rb`

    Fill in the body of this skeleton file with a few more relevant details, such as a user's **name** and **email**.

    ```ruby theme={null}
    class CreateUsers < ActiveRecord::Migration[6.1]
      def change
        create_table :users do |t|
          t.string :name
          t.string :email
          t.timestamps
        end
      end
    end
    ```
  </Step>

  <Step>
    Run your migration:

    ```bash theme={null}
    bin/rails db:migrate
    ```
  </Step>

  <Step>
    Now, give it a whirl to make sure you can query the new table with the `pscale` CLI:

    ```bash theme={null}
    pscale shell blog main
    ```

    ```sql expandable theme={null}
    blog/main> show tables;
    +----------------------+
    | Tables_in_blog       |
    +----------------------+
    | ar_internal_metadata |
    | schema_migrations    |
    | users                |
    +----------------------+
    blog/main> describe users;
    +------------+--------------+------+-----+---------+----------------+
    | Field      | Type         | Null | Key | Default | Extra          |
    +------------+--------------+------+-----+---------+----------------+
    | id         | bigint       | NO   | PRI | NULL    | auto_increment |
    | name       | varchar(255) | YES  |     | NULL    |                |
    | email      | varchar(255) | YES  |     | NULL    |                |
    | created_at | datetime(6)  | NO   |     | NULL    |                |
    | updated_at | datetime(6)  | NO   |     | NULL    |                |
    +------------+--------------+------+-----+---------+----------------+
    ```
  </Step>
</Steps>

## Enable safe migrations

[Safe migrations](/docs/vitess/schema-changes/safe-migrations) is an optional but highly recommended feature for branches on PlanetScale. With safe migrations enabled, direct schema changes (`CREATE`, `ALTER`, and `DELETE`) are not allowed on production branches to prevent accidental data loss and must be applied via [deploy requests](/docs/vitess/best-practices).

```bash theme={null}
pscale branch safe-migrations enable blog main
```

Congratulations! You're ready to develop your Rails application against PlanetScale.

## Summary

In this tutorial, you created a simple Rails application named *blog* and connected it to a PlanetScale database.

## Further reading

If you're interested in learning how to secure your application's connection to PlanetScale, please read [Connecting to PlanetScale securely](/docs/vitess/connecting/secure-connections).

## What's next?

Now that you've successfully connected your Rails app to PlanetScale, it's time to make more schema changes to your tables! Learn more about how PlanetScale allows you to make [non-blocking schema changes](/docs/vitess/schema-changes) to your database, or how to keep your **schema\_migrations** table up-to-date between development and production branches with [automatic schema migrations](/docs/vitess/tutorials/automatic-rails-migrations).

## Need help?

Get help from [the PlanetScale Support team](https://planetscale.com/contact?initial=support), or join our [Discord community](https://pscale.link/community) to see how others are using PlanetScale.
