PostgreSQL’s citext extension provides case-insensitive text fields, which are useful when you want to ensure uniqueness or perform comparisons without worrying about letter casing. In Ash, you can take advantage of citext by using the :ci_string type. Here’s how to set it up.

Add the citext extension to your repository

AshPostgres allows you to manage PostgreSQL extensions through your repo module. To enable citext, update your repo:

defmodule MyApp.Repo do
  use AshPostgres.Repo,
    otp_app: :my_app

  @impl true
  def installed_extensions do
    # Add the citext extension here
    ["ash-functions", "citext"]
  end
end

Update your resource to use :ci_string

In your resource module, change the attribute type to :ci_string and mark it as a unique identity:

defmodule MyApp.Core.Vehicle do
  use Ash.Resource,
    domain: MyApp.Core,
    data_layer: AshPostgres.DataLayer

  postgres do
    table "vehicles"
    repo MyApp.Repo
  end

  attributes do
    uuid_primary_key :id

    attribute :name, :ci_string do
      allow_nil? false
    end

    timestamps()
  end

  identities do
    identity :unique_name, [:name], message: "Name must be unique"
  end
end

Generate and apply the migrations

Finally, generate and run the migrations to apply the changes:

mix ash_postgres.generate_migrations unique_vehicle_name
mix ash_postgres.migrate

Now your name field will use PostgreSQL's citext type, ensuring case-insensitive uniqueness at the database level.