DSL for defining tabular-data validation schemas.
use Scrutinex.Schema (with optional strict: true) imports the column/2,
column/3, and check/2/check/3 macros and registers a __schema__/0
callback at compile time.
Supported types
:string, :integer, :float, :boolean, :date, :datetime
Column options
:required- fail if the column key is missing (defaulttrue):coerce- attempt type casting before validation (defaultfalse):on_empty- behaviour when a cell isnilor""(default:error)::error— severity:error, skips remaining checks:warn— severity:warning, skips remaining checks, cell becomesnilin result data:ignore— no error, skips remaining checks
:nullable- accepted as compile-time sugar foron_empty: :ignore; cannot be combined with:on_empty:checks- keyword list of built-in checks:number: [greater_than: 0, less_than: 100]inclusion: ["A", "B", "C"]exclusion: ["X"]format: ~r/^[A-Z]/length: [min: 1, max: 255]custom: &my_function/1
Strict mode
Pass strict: true to use Scrutinex.Schema to reject rows that contain
columns not declared in the schema.
Cross-column checks
Use the check macro to validate relationships between columns. The block
receives the full row map and must return a truthy value to pass.
Trust Boundary
Schema definitions, including custom check functions and cross-column check blocks, are trusted code. They execute with the same privileges as your application. Do not construct schemas from untrusted user input.
Example
defmodule MyApp.PeopleSchema do
use Scrutinex.Schema, strict: true
column "name", :string, checks: [length: [min: 1, max: 100]]
column "age", :integer, coerce: true, checks: [number: [greater_than: 0]]
column "email", :string, checks: [format: ~r/@/]
column ~r/^score_/, :float, required: false, on_empty: :ignore
check :age_name_consistency do
fn row -> !(row["age"] > 150 && row["name"] == "") end
end
end
result = Scrutinex.validate(data, MyApp.PeopleSchema)