Skip to content

Instantly share code, notes, and snippets.

@amos-kibet
Forked from wosephjeber/instructions.md
Created September 12, 2024 12:53
Show Gist options
  • Save amos-kibet/8e830ca51933519e80eb7b552f0c789d to your computer and use it in GitHub Desktop.
Save amos-kibet/8e830ca51933519e80eb7b552f0c789d to your computer and use it in GitHub Desktop.
Ecto migration for renaming table with indexes and constraints

Renaming table in Ecto migration

I recently wanted to rename a model and its postgres table in a Phoenix app. Renaming the table was simple and documented, but the table also had constraints, sequences, and indexes that needed to be updated in order for the Ecto model to be able to rely on default naming conventions. I couldn't find any examples of what this would look like but was eventually able to figure it out. For anyone else in the same situation, hopefully this example helps.

In the example below, I'm renaming the Permission model to Membership. This model belongs to a User and an Account, so it has foreign key constraints that need to be renamed.

defmodule MyApp.Repo.Migrations.RenamePermissionsToMemberships do
  use Ecto.Migration

  def up do
    # Drop the existing forgeign key and primary key constraints by their
    # default names from when they were generated automatically by Ecto.
    drop constraint(:permissions, "permissions_user_id_fkey")
    drop constraint(:permissions, "permissions_account_id_fkey")
    drop constraint(:permissions, "permissions_pkey")

    # Rename the table
    rename table(:permissions), to: table(:memberships)

    alter table(:memberships) do
      # "Modifying" the columns rengenerates the constraints with the correct
      # new names. These were the same types and options the columns were
      # originally created with in previous migrations.
      modify :id, :bigint, primary_key: true
      modify :user_id, references(:users)
      modify :account_id, references(:accounts)
    end

    # Rename the ID sequence. I don't think this affects Ecto, but it keeps
    # the naming and structure of the table more consistent.
    execute "ALTER SEQUENCE permissions_id_seq RENAME TO memberships_id_seq;"
  end
  
  # This is just the inverse, restoring the table and its constraints,
  # indexes, and sequences to their original names.
  def down do
    drop constraint(:memberships, "memberships_user_id_fkey")
    drop constraint(:memberships, "memberships_account_id_fkey")
    drop constraint(:memberships, "memberships_pkey")

    rename table(:memberships), to: table(:permissions)

    alter table(:permissions) do
      modify :id, :bigint, primary_key: true
      modify :user_id, references(:users)
      modify :account_id, references(:accounts)
    end

    execute "ALTER SEQUENCE memberships_id_seq RENAME TO permissions_id_seq;"
  end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment