Search documentation of bb

# BB.Unit.Option (bb v0.8.0)

View Source

Functions for specifying and validating units in option schemas.

# Summary

## Types

schema_option()
schema_options()

## Functions

unit_type(options \\ [])

Create a Spark.Options schema type for a unit.

validate(value, options \\ [])

Validate a value against a category.

# Types

# schema_option()

    @type schema_option() ::
      {:compatible, atom() | String.t()}
      | {:min, Cldr.Unit.t()}
      | {:max, Cldr.Unit.t()}
      | {:eq, Cldr.Unit.t()}

# schema_options()

    @type schema_options() :: [schema_option()]

# Functions

# unit_type(options \\ [])

    @spec unit_type(Keyword.t()) :: {:custom, BB.Unit.Option, :validate, [Keyword.t()]}

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)]]}

# validate(value, options \\ [])

    @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