View Source Schemas
Strukt builds on Ecto.Schema
, so much of what you need to know can be found in the
Ecto docs. However, there are a few quality-of-life improvements
implemented in Strukt that extend the schema syntax to allow for some additional functionality.
schema-extensions
Schema Extensions
The following is list of the changes we've made to the syntax provided by Ecto.Schema
:
- Support for defining validations inline with the field definition, i.e. alongside standard
options provided to
field
/embeds_one
/embeds_many
. - Support for autogenerated fields with
embedded_schema
. Typically autogenerated fields in Ecto are intended to be provided by the database, but without a database in the loop, nothing happens. Since we're definingnew/1
for the structs we define, it gives us an opportunity to ensure that the autogenerated fields get values immediately on struct creation. - Support for
defstruct
's extended functionality withinembeds_one
/embeds_many
inline definitions, to any arbitrary nesting depth.
One of the biggest quality-of-life improvements provided here is the ability to express
validations inline with the field definition, as well as the automatic generation of validation
code which is automatically applied when you call change/2
or changeset/2
. These build upon
and operate on Ecto.Changeset
, which is a powerful way of expressing constraints, and they
compose well, especially when you have embeds involved.
expressing-validations
Expressing Validations
Let's take a look at the use of inline validation rules, which you pass along with the standard
options to macros like field/3
. The following validation options are provided:
required: boolean | Keyword.t
, options same asvalidate_required/3
length: Keyword.t
, options same asvalidate_length/3
format: Keyword.t
, options same asvalidate_format/4
one_of: list(term) | [values: list(term), message: String.t]
, i.e.validate_inclusion/4
none_of: list(term) | [values: list(term), message: String.t]
, i.e.validate_exclusion/4
subset_of: list(term) | [values: list(term), message: String.t]
, i.e.validate_subset/4
range: Range.t | [value: Range.t, message: String.t]
, i.e.validate_inclusion/4
number: Keyword.t
, i.e.validate_number/4
In all of the above, you can provide a custom validation message using the keyword list variant,
and setting :message
to the desired format string.
custom-validations
Custom Validations
If you need to perform custom validation, or express conditional constraints, then you can override
the definition of validate/1
, which takes an Ecto.Changeset
on which you can apply arbitrary
validation logic. This callback is also invoked any time you call new/1
, so be aware that if you need
to conditionally apply validation rules, you will need to be able to determine the condition from
the data the changeset is based on, see the Ecto.Changeset
API if you aren't sure how to do that.