189 words, 1 min read

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.