Current section
Files
Jump to
Current section
Files
lib/validation/validation.ex
defprotocol Rubbergloves.Validation do
alias Rubbergloves.Errors.Validation.ValidationError
@fallback_to_any true
@spec valid?(any) :: Boolean.t
def valid?(validation)
@spec errors(any) :: ValidationError | []
def errors(validation)
end
defimpl Rubbergloves.Validation, for: Justify.Dataset do
alias Rubbergloves.Errors.Validation.ValidationError
def valid?(dataset), do: dataset.valid?
def errors(dataset), do: %ValidationError{ errors: dataset.errors}
end
defimpl Rubbergloves.Validation, for: Any do
alias Rubbergloves.Errors.Validation.ValidationError
def valid?(:ok), do: true
def valid?(:invalid_type), do: false
def errors(:ok), do: []
def errors(:invalid_type), do: %ValidationError{ errors: [{:type, "Invalid type"}]}
end
defmodule Rubbergloves.Validator do
# @callback required(struct(), atom()) :: any()
@callback required(struct(), atom()) :: any()
@callback type(struct(), atom(), any()) :: any()
end
defmodule Rubbergloves.Validator.Justify do
alias Justify.Validators
@behaviour Rubbergloves.Validator
@impl true
def required(struct, key), do: Justify.validate_required(struct, [key])
@impl true
def type(struct, key, type), do: Validators.Type.call(struct, key, type)
end
defmodule Justify.Validators.Type do
def call(dataset, field, type) do
dataset = Justify.Dataset.new(dataset)
value = Map.get(dataset.data, field)
with :ok <- confirm_type(value, type) do
dataset
else
:error ->
Justify.add_error(dataset, field, "has invalid type expected #{type}", validation: :type)
{:error, error} ->
Justify.add_error(dataset, field, error, validation: :type)
end
end
defp confirm_type(nil, _), do: :ok
defp confirm_type(value, :string) when is_binary(value), do: :ok
defp confirm_type(value, :integer) when is_integer(value), do: :ok
defp confirm_type(value, :map) when is_map(value), do: :ok
defp confirm_type(value, {:one, atom}) when is_atom(atom) and is_map(value) do
type = Map.get(value, :__struct__, nil)
if(type == atom) do
:ok
else
{:error, "has invalid type expected one #{atom} struct"}
end
end
defp confirm_type(_, {:one, atom}) when is_atom(atom), do: {:error, "has invalid type expected one #{atom} struct"}
defp confirm_type([], {:many, atom}) when is_atom(atom), do: :ok
defp confirm_type(value, {:many, atom}) when is_atom(atom) and is_list(value) do
all = Enum.all?(value, fn item ->
case item do
%{__struct__: type} ->
type == atom
_ -> false
end
end)
if(all) do
:ok
else
{:error, "has invalid type expected a list of type: #{atom}"}
end
end
defp confirm_type(_, {:many, atom}) when is_atom(atom), do: {:error, "has invalid type expected a list of type: #{atom}"}
defp confirm_type(_, _), do: :error
end