Tae
Tae

Reputation: 313

How to use Complex Constraint in Ecto?

This is what I want to implement

1. Customer can create a contact with name and phone number.
2. Customer can not create a contact with already existing phone number.

So I did like this…

schema "people" do
    field :name, :string
    field :phone_number, :string
    belongs_to :phonebook, Phonebook

    timestamps()
  end

  def changeset(%Person{} = person, attrs) do
    person
    |> cast(attrs, [:name, :phone_number])
    |> validate_required([:name, :phone_number])
    |> unique_constraint(:phone_number])
  end

and in migration file

create unique_index(:people, [:phone_number)

But other customer can not create a contact with same number because other customer may has a same number. So what is solution for this? I looked up Ecto document and found https://hexdocs.pm/ecto/Ecto.Changeset.html#unique_constraint/3 1

Complex Constraints

is this correct solution? I have tried this as documented, but it won’t work.

Upvotes: 0

Views: 201

Answers (1)

Badu
Badu

Reputation: 1082

One way is to have a customer_id field in the schema. Then apply the unique constraint to both the phone_number and customer_id field. In that case, the phone number will be scoped by the customer that added. When a customer creates a contact, set the contact's customer_id to the customer's id

In migration file

create table(:people) do
  ...
  add :customer_id, :integer
end

create unique_index(:people, [:phone_number, :customer_id], name: :people_phone_number_customer_id_index)

In model module

schema "people" do
field :name, :string
field :phone_number, :string
field :customer_id, :integer
belongs_to :phonebook, Phonebook

timestamps()

end

def changeset(%Person{} = person, attrs) do
person
|> cast(attrs, [:name, :phone_number, :customer_id])
|> validate_required([:name, :phone_number, :customer_id])
|> unique_constraint(:phone_number, name: :people_phone_number_customer_id_index)
end

Upvotes: 2

Related Questions