constructor v1.0.0-rc.1 Constructor behaviour
Constructor is a library that reduces boilerplate when defining stucts by enabling per-field validations and generating methods that are used to "construct" a struct.
A simple example is the following:
defmodule DocTestUser do
use Constructor
constructor do
field :id, :integer, construct: &Validate.is_integer/1
field :first_name, :string, default: "", construct: &Validate.is_string/1
field :last_name, :string, default: "", construct: &Validate.is_string/1
end
end
DocTestUser.new(id: "foo", first_name: 37)
{:error, {:constructor, [id: "must be an integer", first_name: "must be an integer"]}}
iex> DocTestUser.new(id: 12, first_name: "Chris")
{:ok, %DocTestUser{id: 12, first_name: "Chris", last_name: ""}}
iex> DocTestUser.new!(id: 12, first_name: "Chris")
%DocTestUser{id: 12, first_name: "Chris", last_name: ""}
A few things to note here:
new/1
andnew!/1
functions are generated, and accept a map, keyword list or a list of maps- The
:construct
functions are run for each field, and any errors are returned in a keyword list default
values are applied before the:construct
functionsConstructor.Validate
andConstructor.Convert
are automatically aliased- the
:construct
attribute accepts either a function capture (as above), a {M,F,A} tuple, or a list of function captures or MFA tuples.
Any function that conforms to t:constructor_fun/1
can be used in the construct
field.
Additionally, a new/1
function can also be used to build out a nested struct. For example:
defmodule DocTestAdmin do
use Constructor
constructor do
field :id, :integer, construct: &Validate.is_integer/1
field :user, DocTestUser.t(), construct: &DocTestUser.new/1
end
end
iex> DocTestAdmin.new!(id: 22, user: %{id: 22, first_name: "Chris"})
%DocTestAdmin{id: 22, user: %DocTestUser{id: 22, first_name: "Chris"}}
Acknowledgements
This library was born from the lack of a lightweight (but powerful!) validation library in Elixir
that doesn't depend on Ecto. The constructor
macro comes almost entirely from the excellent
typed_struct
library, save for a plugin mechanism.
Link to this section Summary
Functions
Declare a struct and it's fields. Set's the default options for the struct
Callbacks
This callback can be used to perform a complex, multi-field validation after all of the per-field validations have run
The callback can be used to modify an input to new/2
before the constructor functions are
called
Build this struct from a map, struct or keyword list. Also accepts a list of maps that will be iterated to convert each to the new function
Same as new/2
, but returns the untagged struct or raises a ConstructorException
Link to this section Types
constructor_fun()
new_opts()
new_opts() :: [{:nil_to_empty, boolean()}]
new_opts() :: [{:nil_to_empty, boolean()}]
Link to this section Functions
constructor(opts \\ [], list) (macro)
Declare a struct and it's fields. Set's the default options for the struct.
Opts
nil_to_empty
: iftrue
, convert a nilinput
into an empty struct. Defaults totrue
Link to this section Callbacks
after_construct(struct)
This callback can be used to perform a complex, multi-field validation after all of the per-field validations have run.
before_construct(any)
The callback can be used to modify an input to new/2
before the constructor functions are
called.
new(input)
new(input, opts)
Build this struct from a map, struct or keyword list. Also accepts a list of maps that will be iterated to convert each to the new function.
Opts
nil_to_empty
: iftrue
, convert a nilinput
into an empty struct. Defaults totrue
new!(input)
new!(input, opts)
Same as new/2
, but returns the untagged struct or raises a ConstructorException