Current section
Files
Jump to
Current section
Files
lib/type/boolean.ex
defmodule Litmus.Type.Boolean do
@moduledoc false
alias Litmus.Required
@truthy_default [true, "true"]
@falsy_default [false, "false"]
defstruct truthy: @truthy_default,
falsy: @falsy_default,
required: false
@type t :: %__MODULE__{
truthy: [term],
falsy: [term],
required: boolean
}
@spec validate_field(t, String.t(), map) :: {:ok, map} | {:error, String.t()}
def validate_field(type, field, data) do
with {:ok, data} <- Required.validate(type, field, data),
{:ok, data} <- truthy_falsy_validate(type, field, data) do
{:ok, data}
else
{:error, msg} -> {:error, msg}
end
end
@spec check_boolean_values(term, [term], [term]) :: boolean
defp check_boolean_values(initial_value, additional_values, default_values)
when is_binary(initial_value) do
allowed_values =
additional_values
|> (&(&1 ++ default_values)).()
|> Enum.uniq()
|> Enum.map(fn item ->
if is_binary(item) do
String.downcase(item)
end
end)
String.downcase(initial_value) in allowed_values
end
defp check_boolean_values(initial_value, additional_values, default_values) do
initial_value in Enum.uniq(additional_values ++ default_values)
end
@spec truthy_falsy_validate(t, String.t(), map) :: {:ok, map} | {:error, String.t()}
defp truthy_falsy_validate(%__MODULE__{falsy: falsy, truthy: truthy}, field, params) do
cond do
!Map.has_key?(params, field) ->
{:ok, params}
check_boolean_values(params[field], truthy, @truthy_default) ->
{:ok, Map.replace!(params, field, true)}
check_boolean_values(params[field], falsy, @falsy_default) ->
{:ok, Map.replace!(params, field, false)}
true ->
{:error, "#{field} must be a boolean"}
end
end
defimpl Litmus.Type do
alias Litmus.Type
@spec validate(Type.t(), String.t(), map) :: {:ok, map} | {:error, String.t()}
def validate(type, field, data), do: Type.Boolean.validate_field(type, field, data)
end
end