defmodule Bbox.Candidates.Candidate do
@moduledoc """
Candidate in the election and belongs to a party.
"""
use Ecto.Schema
import Ecto.Changeset
alias Bbox.Parties.Party
alias Bbox.Votes.Vote
@primary_key false
@foreign_key_type :string
@derive {Jason.Encoder, except: [:__meta__, :party, :votes]}
schema "candidates" do
field(:first_name, :string)
field(:last_name, :string)
field(:email, :string)
field(:code, :string)
belongs_to(:party, Party, foreign_key: :party_initials, references: :initials)
has_many(:votes, Vote, foreign_key: :candidate_code, references: :code)
timestamps()
end
def changeset(candidate, params \\ %{}) do
candidate
|> cast(params, [:first_name, :last_name, :email])
|> validate_required([:first_name, :last_name, :email])
|> validate_format(:email, ~r/^\S+@\S+\.\S+$/, message: "invalid email")
|> validate_length(:first_name, min: 3, message: "first name must be at least 3 characters")
|> validate_length(:last_name, min: 3, message: "last name must be at least 3 characters")
|> unique_constraint(:email, message: "email already exists")
|> generate_code()
|> unique_constraint(:code, message: "code already exists")
end
defp generate_code(%Ecto.Changeset{valid?: true} = changeset) do
code =
4
|> :crypto.strong_rand_bytes()
|> :binary.encode_hex()
change(changeset, %{code: code})
end
defp generate_code(changeset), do: changeset
end