Current section
Files
Jump to
Current section
Files
lib/ecto/changeset.ex
defmodule AntlDateTimeUtils.Ecto.Changeset do
@moduledoc """
Utils for Ecto.Changeset around DateTime
"""
import Ecto.Changeset
alias AntlDateTimeUtils.Comparison
alias AntlDateTimeUtils.Period
@spec validate_datetime_lt(Ecto.Changeset.t(), atom, atom | nil | DateTime.t(), keyword) ::
Ecto.Changeset.t()
def validate_datetime_lt(changeset, datetime_key, referal, opts \\ [])
def validate_datetime_lt(
%Ecto.Changeset{} = changeset,
datetime_key,
referal_datetime_key,
opts
)
when is_atom(datetime_key) and is_atom(referal_datetime_key) and
not is_nil(referal_datetime_key) do
opts = Keyword.put_new(opts, :message, "should be before #{referal_datetime_key}")
{_, referal_datetime} = fetch_field(changeset, referal_datetime_key)
validate_datetime_lt(changeset, datetime_key, referal_datetime, opts)
end
def validate_datetime_lt(
%Ecto.Changeset{} = changeset,
datetime_key,
referal_datetime,
opts
)
when is_atom(datetime_key) do
message = Keyword.get(opts, :message, "should be before #{referal_datetime}")
{_, datetime} = fetch_field(changeset, datetime_key)
if datetime_lt?(datetime, referal_datetime) do
changeset
else
changeset |> add_error(datetime_key, message)
end
end
@spec validate_datetime_lte(Ecto.Changeset.t(), atom, atom | nil | DateTime.t(), keyword) ::
Ecto.Changeset.t()
def validate_datetime_lte(changeset, datetime_key, referal, opts \\ [])
def validate_datetime_lte(
%Ecto.Changeset{} = changeset,
datetime_key,
referal_datetime_key,
opts
)
when is_atom(datetime_key) and is_atom(referal_datetime_key) and
not is_nil(referal_datetime_key) do
opts = Keyword.put_new(opts, :message, "should be before or equal to #{referal_datetime_key}")
{_, referal_datetime} = fetch_field(changeset, referal_datetime_key)
validate_datetime_lte(changeset, datetime_key, referal_datetime, opts)
end
def validate_datetime_lte(%Ecto.Changeset{} = changeset, datetime_key, referal_datetime, opts)
when is_atom(datetime_key) do
message = Keyword.get(opts, :message, "should be before or equal to #{referal_datetime}")
{_, datetime} = fetch_field(changeset, datetime_key)
if datetime_lte?(datetime, referal_datetime) do
changeset
else
changeset |> add_error(datetime_key, message)
end
end
@spec validate_datetime_gt(Ecto.Changeset.t(), atom() | nil | DateTime.t(), atom(), keyword) ::
Ecto.Changeset.t()
def validate_datetime_gt(changeset, datetime_key, referal, opts \\ [])
def validate_datetime_gt(
%Ecto.Changeset{} = changeset,
datetime_key,
referal_datetime_key,
opts
)
when is_atom(datetime_key) and is_atom(referal_datetime_key) and
not is_nil(referal_datetime_key) do
opts = Keyword.put_new(opts, :message, "should be after #{referal_datetime_key}")
{_, referal_datetime} = fetch_field(changeset, referal_datetime_key)
validate_datetime_gt(changeset, datetime_key, referal_datetime, opts)
end
def validate_datetime_gt(%Ecto.Changeset{} = changeset, datetime_key, referal_datetime, opts)
when is_atom(datetime_key) do
message = Keyword.get(opts, :message, "should be after #{referal_datetime}")
{_, datetime} = fetch_field(changeset, datetime_key)
if datetime_gt?(datetime, referal_datetime) do
changeset
else
changeset |> add_error(datetime_key, message)
end
end
@spec validate_datetime_gte(Ecto.Changeset.t(), atom() | nil | DateTime.t(), atom(), keyword) ::
Ecto.Changeset.t()
def validate_datetime_gte(changeset, datetime_key, referal, opts \\ [])
def validate_datetime_gte(
%Ecto.Changeset{} = changeset,
datetime_key,
referal_datetime_key,
opts
)
when is_atom(datetime_key) and is_atom(referal_datetime_key) and
not is_nil(referal_datetime_key) do
opts = Keyword.put_new(opts, :message, "should be after or equal to #{referal_datetime_key}")
{_, referal_datetime} = fetch_field(changeset, referal_datetime_key)
validate_datetime_gte(changeset, datetime_key, referal_datetime, opts)
end
def validate_datetime_gte(%Ecto.Changeset{} = changeset, datetime_key, referal_datetime, opts)
when is_atom(datetime_key) do
message = Keyword.get(opts, :message, "should be after or equal to #{referal_datetime}")
{_, datetime} = fetch_field(changeset, datetime_key)
if datetime_gte?(datetime, referal_datetime) do
changeset
else
changeset |> add_error(datetime_key, message)
end
end
@spec validate_datetime_inclusion(Ecto.Changeset.t(), atom, atom, map, atom, atom) ::
Ecto.Changeset.t()
def validate_datetime_inclusion(
%Ecto.Changeset{} = changeset,
start_at_key,
end_at_key,
period,
period_start_at_key,
period_end_at_key
)
when is_atom(period_start_at_key) and is_atom(period_end_at_key) do
container_period = %{
start_at: Map.get(period, period_start_at_key),
end_at: Map.get(period, period_end_at_key)
}
validate_datetime_inclusion(changeset, start_at_key, end_at_key, container_period)
end
@spec validate_datetime_inclusion(Ecto.Changeset.t(), atom, atom, Period.t()) ::
Ecto.Changeset.t()
def validate_datetime_inclusion(%Ecto.Changeset{} = changeset, _, _, %{
start_at: nil,
end_at: nil
}) do
changeset
end
def validate_datetime_inclusion(
%Ecto.Changeset{} = changeset,
start_at_key,
end_at_key,
%{start_at: _, end_at: _} = container_period
)
when is_atom(start_at_key) and is_atom(end_at_key) do
{_, included_start_at} = fetch_field(changeset, start_at_key)
{_, included_end_at} = fetch_field(changeset, end_at_key)
included_period = %{start_at: included_start_at, end_at: included_end_at}
unless Period.included?(included_period, container_period) do
changeset
|> add_error(
start_at_key,
"#{start_at_key} and #{end_at_key} are out of bound [#{container_period.start_at}, #{
container_period.end_at
}]"
)
else
changeset
end
end
defp datetime_gt?(nil, nil), do: true
defp datetime_gt?(_, nil), do: false
defp datetime_gt?(nil, %DateTime{}), do: true
defp datetime_gt?(%DateTime{} = end_at, %DateTime{} = start_at),
do: Comparison.gt?(end_at, start_at)
defp datetime_gte?(nil, nil), do: true
defp datetime_gte?(_, nil), do: false
defp datetime_gte?(nil, %DateTime{}), do: true
defp datetime_gte?(%DateTime{} = end_at, %DateTime{} = start_at),
do: Comparison.gte?(end_at, start_at)
defp datetime_lt?(nil, nil), do: true
defp datetime_lt?(_, nil), do: true
defp datetime_lt?(nil, %DateTime{}), do: false
defp datetime_lt?(%DateTime{} = end_at, %DateTime{} = start_at),
do: Comparison.lt?(end_at, start_at)
defp datetime_lte?(nil, nil), do: true
defp datetime_lte?(_, nil), do: true
defp datetime_lte?(nil, %DateTime{}), do: false
defp datetime_lte?(%DateTime{} = end_at, %DateTime{} = start_at),
do: Comparison.lte?(end_at, start_at)
end