Creating Unique Constraint/Index Ecto.Migration: Elixir

Have you ever found yourself in a position where you can find anything about something you really need? Just happen to encounter this problem doing my task for a company I’m working with and I can’t find proper documentation about it. So here it is, hope I'm the last one who had troubles trying and finding the right way to do this.

Migration

Let's start with the migration, say you want to create a movie table with two fields (title and genre) and you don't want to create entries with duplicate values of those fields.

create table(:movies) do
add(:genre, :string)
add(:title, :string)
timestamps()
end
create(
unique_index(
:movies,
~w(title genre)a,
name: :index_for_movies_duplicate_entries
)
)

index_for_movies_duplicate_entries: can be any name you want, can also be automatically generated based on the fields included on your constraint.

~w(title genre)a: a list of fields to checks for a unique constraint. Can also be [:title, :genre], I just like the sigil one.

Schema

Make sure to pipe the unique_constraint/3 on your changeset.

defmodule Data.Schemas.Movie do
use Data.Schema
schema "movies" do
field(:genre, :string)
field(:title, :string)
timestamps()
end
@required ~w(title)a
@optional ~w(genre)a
def changeset(struct, params \\ %{}) do
struct
|> cast(params, @optional ++ @required)
|> validate_required(@required)
|> unique_constraint(
:title,
name: :index_for_movies_duplicate_entries
)

end
end

The 2nd parameter of unique_constraint/3 can be any field that’s a part of the constraint, in this case, the title.

Testing

Wanna know how to test this? check out the full story on my website: Creating Unique Constraint/Index Ecto.Migration: Elixir

And there you have it. hope this can help. 🎉