NLdoc.Spec.Schema (NLdoc.Spec v3.1.1)

View Source

This module sets some defaults over the Ecto schema for the NLdoc spec.

  1. Use this in all schemas for the NLdoc spec, instead of use Ecto.Schema or use TypedEctoSchema: use NLdoc.Spec.Schema, type: "https://spec.nldoc.nl/Resource/Foo"
  2. Implement the changeset/2 function in the schema module.
  3. Make sure to add @cast_opts to all calls to cast/4 or cast_embed/3 or cast_polymorphic_embed/3, as it ensures strings that only contain whitespace are accepted as valid.

Note: the type option is required and must be a string. It is the resource type of the schema. It will be available as @resource_type in the schema module and through the resource_type/0 function on the schema module.

Summary

Functions

Collects all errors from a changeset and its nested changesets into a flat map, mapping the full JSON path of each property to its error.

This macro defines the new/1 and new!/1 functions for the schema module that create a new document from a template, which essentially functions like an input-validating constructor for the struct defined by the schema module.

This macro maps a list of modules to a list of tuples with the module's resource type and the module itself. It's a macro because Ecto's schema definitions require this mapping to be done at compile time.

Returns true if the given module is an existing module.

Returns true for a module that is a schema module, i.e. it has a new/1 and a changeset/2 function.

This function validates whether a string is a valid URL, returning nil if it's valid and an Ecto.Changeset.error() if it's not.

Types

errors()

@type errors() :: %{required(property :: atom()) => Ecto.Changeset.error()}

validate_url_opt()

@type validate_url_opt() :: {:allow_relative, boolean()}

Functions

collect_errors(changeset)

@spec collect_errors(Ecto.Changeset.t()) :: errors()

Collects all errors from a changeset and its nested changesets into a flat map, mapping the full JSON path of each property to its error.

Example

iex> changeset = %Ecto.Changeset{
...>   changes: [
...>     descriptors: [
...>       %Ecto.Changeset{errors: [url: {"is invalid", [validation: :invalid_url]}]}
...>     ]
...>   ],
...>   errors: [
...>     name: {"is invalid", [type: :string]}
...>   ]
...> }
iex> NLdoc.Spec.Schema.collect_errors(changeset)
%{
  name: {"is invalid", [type: :string]},
  "descriptors[0].url": {"is invalid", [validation: :invalid_url]}
}

collect_errors(list, parent)

@spec collect_errors(Ecto.Changeset.t(), parent :: atom() | String.t()) :: errors()
@spec collect_errors([Ecto.Changeset.t() | any()], parent :: atom() | String.t()) ::
  errors()

def_constructor(_)

(macro)

This macro defines the new/1 and new!/1 functions for the schema module that create a new document from a template, which essentially functions like an input-validating constructor for the struct defined by the schema module.

map(modules)

(macro)

This macro maps a list of modules to a list of tuples with the module's resource type and the module itself. It's a macro because Ecto's schema definitions require this mapping to be done at compile time.

Example:

> NLdoc.Schema.map([Heading, Image])
[
  "https://spec.nldoc.nl/Resource/Heading": Heading,
  "https://spec.nldoc.nl/Resource/Image": Image
]

module_exists?(module)

@spec module_exists?(module()) :: boolean()

Returns true if the given module is an existing module.

schema_module?(module)

@spec schema_module?(module()) :: boolean()

Returns true for a module that is a schema module, i.e. it has a new/1 and a changeset/2 function.

validate_url(url, opts \\ [])

@spec validate_url(String.t(), [validate_url_opt()]) :: Ecto.Changeset.error() | nil

This function validates whether a string is a valid URL, returning nil if it's valid and an Ecto.Changeset.error() if it's not.

Examples

iex> NLdoc.Spec.Schema.validate_url("http://localhost:4000")
nil

iex> NLdoc.Spec.Schema.validate_url("https://nldoc.nl/path/to/resource?query=string#fragment")
nil

iex> NLdoc.Spec.Schema.validate_url("https://no-tld")
nil

iex> NLdoc.Spec.Schema.validate_url("test")
{"is not a valid URL", error: [invalid_scheme: nil]}

iex> NLdoc.Spec.Schema.validate_url("/path/to/resource")
{"is not a valid URL", error: [invalid_scheme: nil, invalid_host: "/path/to/resource"]}