ash_postgres/lib/migration.ex

73 lines
1.9 KiB
Elixir

defmodule AshPostgres.Migration do
@moduledoc "Utilities for use in migrations"
@doc """
A utility for creating postgres enums for an Ash enum type.
In your migration, you can say:
```elixir
def up() do
AshPostgres.Migration.create_enum(MyEnumType)
end
```
Attribution:
This code and example was copied from ecto_enum. I didn't use the library itself
because it has a lot that would not currently be relevant for Ash.
https://github.com/gjaldon/ecto_enum
Must be done manually, as the migration generator will not do it.
Additionally, altering the type must be done in its own, separate migration, which
must have `@disable_ddl_transaction true`, as you cannot do this operation
in a transaction.
For example:
```elixir
defmodule MyApp.Repo.Migrations.AddToGenderEnum do
use Ecto.Migration
@disable_ddl_transaction true
def up do
Ecto.Migration.execute "ALTER TYPE gender ADD VALUE IF NOT EXISTS 'other'"
end
def down do
...
end
end
```
Keep in mind, that if you want to create a custom enum type, you will want to add
```elixir
def storage_type(_), do: :my_type_name
```
"""
def create_enum(type, constraints \\ []) do
if type.storage_type(constraints) == :string do
raise "Must customize the storage_type for #{type} in order to create an enum"
end
types = Enum.map_join(type.values(), ", ", &"'#{&1}'")
Ecto.Migration.execute(
"CREATE TYPE #{type.storage_type()} AS ENUM (#{types})",
"DROP TYPE #{type.storage_type()}"
)
end
def drop_enum(type) do
if type.storage_type() == :string do
raise "Must customize the storage_type for #{type} in order to create an enum"
end
types = Enum.map_join(type.values(), ", ", &"'#{&1}'")
Ecto.Migration.execute(
"DROP TYPE #{type.storage_type()}",
"CREATE TYPE #{type.storage_type()} AS ENUM (#{types})"
)
end
end