Functions for specifying and validating units in option schemas.
Summary
Types
@type schema_option() :: {:compatible, atom() | String.t()} | {:min, Cldr.Unit.t()} | {:max, Cldr.Unit.t()} | {:eq, Cldr.Unit.t()}
@type schema_options() :: [schema_option()]
Functions
Create a Spark.Options schema type for a unit.
Examples
Basic usage returns a custom schema type tuple:
iex> BB.Unit.Option.unit_type()
{:custom, BB.Unit.Option, :validate, [[]]}With compatible option to restrict unit category:
iex> BB.Unit.Option.unit_type(compatible: :meter)
{:custom, BB.Unit.Option, :validate, [[compatible: :meter]]}With min constraint:
iex> BB.Unit.Option.unit_type(min: Cldr.Unit.new!(:meter, 0))
{:custom, BB.Unit.Option, :validate, [[min: Cldr.Unit.new!(:meter, 0)]]}With max constraint:
iex> BB.Unit.Option.unit_type(max: Cldr.Unit.new!(:meter, 100))
{:custom, BB.Unit.Option, :validate, [[max: Cldr.Unit.new!(:meter, 100)]]}Combined constraints:
iex> BB.Unit.Option.unit_type(compatible: :meter, min: Cldr.Unit.new!(:meter, 0), max: Cldr.Unit.new!(:meter, 100))
{:custom, BB.Unit.Option, :validate, [[compatible: :meter, min: Cldr.Unit.new!(:meter, 0), max: Cldr.Unit.new!(:meter, 100)]]}
@spec validate(any(), Keyword.t()) :: {:ok, Cldr.Unit.t()} | {:ok, BB.Dsl.ParamRef.t()} | {:error, String.t()}
Validate a value against a category.
Examples
Valid unit passes through:
iex> BB.Unit.Option.validate(Cldr.Unit.new!(:meter, 5))
{:ok, Cldr.Unit.new!(:meter, 5)}Non-unit values are rejected:
iex> BB.Unit.Option.validate("not a unit")
{:error, "Value `\"not a unit\"` is not a `Cldr.Unit` struct"}Compatible unit check passes for same category:
iex> BB.Unit.Option.validate(Cldr.Unit.new!(:centimeter, 100), compatible: :meter)
{:ok, Cldr.Unit.new!(:centimeter, 100)}Incompatible units are rejected:
iex> BB.Unit.Option.validate(Cldr.Unit.new!(:degree, 90), compatible: :meter)
{:error, "The unit `degree` is not compatible with `meter`"}Min constraint - value must be >= min:
iex> BB.Unit.Option.validate(Cldr.Unit.new!(:meter, 5), min: Cldr.Unit.new!(:meter, 1))
{:ok, Cldr.Unit.new!(:meter, 5)}
iex> BB.Unit.Option.validate(Cldr.Unit.new!(:meter, 1), min: Cldr.Unit.new!(:meter, 5))
{:error, "Expected 1m to be greater than or equal to 5m"}Max constraint - value must be <= max:
iex> BB.Unit.Option.validate(Cldr.Unit.new!(:meter, 5), max: Cldr.Unit.new!(:meter, 10))
{:ok, Cldr.Unit.new!(:meter, 5)}
iex> BB.Unit.Option.validate(Cldr.Unit.new!(:meter, 15), max: Cldr.Unit.new!(:meter, 10))
{:error, "Expected 15m to be less than or equal to 10m"}Eq constraint - value must equal exactly:
iex> BB.Unit.Option.validate(Cldr.Unit.new!(:meter, 5), eq: Cldr.Unit.new!(:meter, 5))
{:ok, Cldr.Unit.new!(:meter, 5)}
iex> BB.Unit.Option.validate(Cldr.Unit.new!(:meter, 5), eq: Cldr.Unit.new!(:meter, 10))
{:error, "Expected 5 m to equal 10 m"}ParamRef values are accepted and annotated with expected unit type:
iex> ref = BB.Dsl.ParamRef.param([:motion, :max_speed])
iex> {:ok, validated} = BB.Unit.Option.validate(ref, compatible: :meter)
iex> validated.expected_unit_type
:meter