DEV Community

Cover image for How to use unique_index wisely to grasp our business logic
Herminio Torres
Herminio Torres

Posted on

How to use unique_index wisely to grasp our business logic

How do you ensure a unique index when the user tries to get more than one ticket for a paid conference? And the user gets multiple tickets for a free conference?

What are our goals here?

  • sent paid conference to Ticket.changeset/1 to ensure the status: :paid, create one.
  • sent free conference to Ticket.changeset/1 to ensure the status: :free, create many.

How can we apply these to our business logic:

create table(:tickets) do add :conference_id, references(:conferences), null: false add :user_id, references(:users), null: false add :status, :string, null: false, default: "free" end create unique_index(:tickets, [:conference_id, :user_id, :status], where: "status = 'paid'") 
Enter fullscreen mode Exit fullscreen mode

Now, how can we test?

iex> Ticket.changeset(%{conference: %{is_paid: false}, user: %{...}, status: :free}) |> Repo.insert() [debug] QUERY OK {:ok, %Ticket%{id: 1, status: :free, conference_id: 1, user_id: 1} } iex> Ticket.changeset(%{conference: %{is_paid: false}, user: %{...}, status: :free}) |> Repo.insert() [debug] QUERY OK {:ok, %Ticket%{id: 2, status: :free, conference_id: 1, user_id: 1} } iex> Ticket.changeset(%{conference: %{is_paid: true}, user: %{...}, status: :paid}) |> Repo.insert() [debug] QUERY OK {:ok, %Ticket%{id: 3, status: :paid, conference_id: 2, user_id: 1} } iex> Ticket.changeset(%{conference: %{is_paid: true}, user: %{...}, status: :paid}) |> Repo.insert() [debug] QUERY ERROR ** (Ecto.ConstraintError) 
Enter fullscreen mode Exit fullscreen mode

Awesome!

Reference

Top comments (0)