Current section

Files

Jump to
nldoc_ecto lib nldoc ecto validator uri.ex
Raw

lib/nldoc/ecto/validator/uri.ex

defmodule NLdoc.Ecto.Validator.URI do
@moduledoc """
Validator for URI's.
## Example
defmodule User do
use Ecto.Schema
import NLdoc.Ecto.Validator.URI, only: [:validate_uri: 3]
schema "users" do
field :name, :string
field :profile_url, :string
end
def changeset(user, params) do
user
|> Ecto.Changeset.cast(params, [:name, :profile_url])
|> validate_uri(:profile_url, schemes: ["https"])
end
end
"""
@type validate_url_opt() :: {:schemes, [String.t()]}
@spec validate_uri(
changeset :: Ecto.Changeset.t(),
field :: atom(),
opts :: [validate_url_opt()]
) :: Ecto.Changeset.t()
def validate_uri(changeset = %Ecto.Changeset{}, field, opts \\ []) when is_atom(field) do
allowed_schemes = Keyword.get(opts, :schemes, [])
Ecto.Changeset.validate_change(
changeset,
field,
fn ^field, value ->
case do_validate_uri(value, allowed_schemes) do
:ok -> []
{:error, reason} -> [{field, reason}]
end
end
)
end
@spec do_validate_uri(value :: binary(), allowed_schemes :: [String.t()]) ::
:ok | {:error, String.t()}
defp do_validate_uri(value, allowed_schemes) when is_binary(value) do
case URI.new(value) do
{:ok, %URI{scheme: scheme}} ->
cond do
is_nil(scheme) ->
{:error, "must have scheme"}
Enum.empty?(allowed_schemes) ->
:ok
Enum.member?(allowed_schemes, scheme) ->
:ok
true ->
{:error, "has invalid scheme"}
end
{:error, _} ->
{:error, "must be a URI"}
end
end
end