Guides or advice for migrating to Ash?

I have a small app with 3 tables in Postgres using Ecto.Table. I am migrating them to use Ash.Resource. When I run mix ash_postgres.generate_migrations for the first time, the generated migrations are to create tables that already exist and the table structures are different. Are there any guides or do you have any advice for reconciling the differences? Original ecto migration:
defmodule Iterup.Repo.Migrations.CreateAccounts do
use Ecto.Migration

def change do
create table(:accounts, primary_key: false) do
add :id, :binary_id, primary_key: true
add :name, :string
add :slug, :string

timestamps()
end

create unique_index(:accounts, [:slug])
end
end
defmodule Iterup.Repo.Migrations.CreateAccounts do
use Ecto.Migration

def change do
create table(:accounts, primary_key: false) do
add :id, :binary_id, primary_key: true
add :name, :string
add :slug, :string

timestamps()
end

create unique_index(:accounts, [:slug])
end
end
New generated migration:
defmodule Iterup.Repo.Migrations.MigrateResources1 do
@moduledoc """
Updates resources based on their most recent snapshots.

This file was autogenerated with `mix ash_postgres.generate_migrations`
"""

use Ecto.Migration

def up do
create table(:accounts, primary_key: false) do
add :id, :uuid, null: false, default: fragment("uuid_generate_v4()"), primary_key: true
add :name, :text, null: false
add :slug, :text, null: false
add :inserted_at, :utc_datetime_usec, null: false, default: fragment("now()")
add :updated_at, :utc_datetime_usec, null: false, default: fragment("now()")
end
end

def down do
drop table(:accounts)
end
end
defmodule Iterup.Repo.Migrations.MigrateResources1 do
@moduledoc """
Updates resources based on their most recent snapshots.

This file was autogenerated with `mix ash_postgres.generate_migrations`
"""

use Ecto.Migration

def up do
create table(:accounts, primary_key: false) do
add :id, :uuid, null: false, default: fragment("uuid_generate_v4()"), primary_key: true
add :name, :text, null: false
add :slug, :text, null: false
add :inserted_at, :utc_datetime_usec, null: false, default: fragment("now()")
add :updated_at, :utc_datetime_usec, null: false, default: fragment("now()")
end
end

def down do
drop table(:accounts)
end
end
Thanks in advance. Excited to move to Ash.
2 Replies
ZachDaniel
ZachDaniel•3y ago
The best way to handle this is generally to generate migrations once, replace the generated migrations with migrations that would change your schema to the new schema, and then move forward with the generated migrations. Generating the migrations once will store the snapshots, and then only new changes will be generated in the future. So, for example, you might replace the generated migration with something like:
modify table(:accounts) do
# binary -> uuid should be safe as they are stored as binaries IIRC
alter :id, :uuid, null: false, default: fragment("uuid_generate_v4()"), primary_key: true
# string -> text are synonyms IIRC
alter :name, :text, null: false
alter :slug, :text, null: false
alter :inserted_at, :utc_datetime_usec, null: false, default: fragment("now()")
alter :updated_at, :utc_datetime_usec, null: false, default: fragment("now()")
end
modify table(:accounts) do
# binary -> uuid should be safe as they are stored as binaries IIRC
alter :id, :uuid, null: false, default: fragment("uuid_generate_v4()"), primary_key: true
# string -> text are synonyms IIRC
alter :name, :text, null: false
alter :slug, :text, null: false
alter :inserted_at, :utc_datetime_usec, null: false, default: fragment("now()")
alter :updated_at, :utc_datetime_usec, null: false, default: fragment("now()")
end
Might take a couple iterations to get right, but AFAIK that is the best way to go about it 🙂
Robert Graff
Robert GraffOP•3y ago
Thanks. I'll give that a go!

Did you find this page helpful?