Contrak.Schema (Contrak v0.3.0) View Source

This is only a specification to define a schema to use with Contract.validate

Schema is just a map or keyword list that follow some simple conventions. Map's key is the field name and the value is a keyword list of field specifications.

Example

%{
  name: [type: :string, format: ~r/{4}/],
  age: [type: :integer, number: [min: 15, max: 50]].
  skill: [type: {:array, :string}, length: [min: 1, max: 10]]
}

If you only specify type of data, you can write it shorthand style like this

%{
  name: :string,
  age: :integer,
  skill: {:array, :string}
}

I. Field type

Built-in types

A type could be any of built-in supported types:

  • boolean
  • string | binary
  • integer
  • float
  • number (integer or float)
  • date
  • time
  • datetime | utc_datetime: date time with time zone
  • naive_datetime: date time without time zone
  • map
  • keyword
  • {array, type} array of built-in type, all item must be the same type

Other types Custom type may be supported depends on module.

Nested types Nested types could be a another schema or list of schema

%{
  user: [type: %{
      name: [type: :string]
    }]
}

Or list of schema

%{
  users: [type: {:array, %{
      name: [type: :string]
    }} ]
}

II. Field casting and default value

These specifications is used for casting data with Contrak.Params.cast

1. Default value

Is used when the given field is missing or nil.

  • Default could be a value

    %{
      status: [type: :string, default: "active"]
    }
  • Or a function/0, this function will be invoke each time data is casted

    %{
      published_at: [type: :datetime, default: &DateTime.utc_now/0]
    }

2. Custom cast function

You can provide a function to cast field value instead of using default casting function by using cast_func: <function/1>

%{
    published_at: [type: :datetime, cast_func: &DateTime.from_iso8601/1]
}

III. Field validation

These validation are supported by Contrak.Validator

1. Type validation

Type specification above could be used for validating or casting data.

2. Numeric validation

Support validating number value. These are list of supported validations:

  • equal_to
  • greater_than_or_equal_to | min
  • greater_than
  • less_than
  • less_than_or_equal_to | max

Define validation: number: [<name>: <value>, ...]

Example

%{
  age: [type: :integer, number: [min: 1, max: 100]]
}

3. Length validation

Validate length of supported types include string, array, map, tuple, keyword. Length condions are the same with Numeric validation

Define validation: length: [<name>: <value>, ...]

Example

%{
  skills: [type: {:array, :string}, length: [min: 0, max: 5]]
}

4. Format validation

Check if a string match a given pattern.

Define validation: format: <Regex>

Example

%{
  year: [type: :string, format: ~r/year: {4}/]
}

5. Inclusion and exclusion validation

Check if value is included or not included in given enumerable (array, map, or keyword)

Define validation: in: <enumerable> or not_in: <enumerable>

Example

%{
  status: [type: :string, in: ["active", "inactive"]],
  selected_option: [type: :integer, not_in: [2,3]]
}

6. Custom validation function

You can provide a function to validate the value.

Define validation: func: <function>

Function must be follow this signature

@spec func(value::any()) :: :ok | {:error, message::String.t()}

Link to this section Summary

Functions

Expand short-hand type syntax to full syntax

Link to this section Functions

Specs

expand(map()) :: map()

Expand short-hand type syntax to full syntax

field: :string -> field: [type: :string]
field: {:array, :string} -> field: [type: {:array, :string}]
field: %{#embedded} -> field: [type: %{#embedded}]