Skip to main content

Data validation

In Rune, data validation ensures that your model stays consistent and accurate. Think of these components as a built-in ‘health check’ for your data objects. When you define validation rules, Rune generates executable code that can scan your data and report exactly which rules passed and which were broken.

There are two types of validation components:

  1. Cardinality
  2. Condition statements

1. CardinalityCardinality The number of elements in a set or other grouping, as a property of that grouping.

CardinalityCardinality The number of elements in a set or other grouping, as a property of that grouping. is the simplest form of validation. It controls how many instances of an attribute are allowed. It defines the ‘lower bound’ (minimum – x) and ‘upper bound’ (maximum – y) for an attribute. This prevents missing data or prevents an object from having too many entries where only one is expected.

Syntax

Rune uses the standard (x..y) notation:

  • (0..1): Optional. The attribute can be missing or appear once.
  • (1..1): Mandatory. There must be exactly one.
  • (1..*): List. At least one is required, but there is no upper limit.
  • (0..*): Optional list. Any number (including zero) is allowed.

Example

type Address:
street string (1..*)
city string (1..1)
state string (0..1)
country string (1..1)
[metadata scheme]
postalCode string (1..1)

2. Condition statements

Conditions are custom logic rules you can use to check if the data within an object makes sense. Conditions evaluate to True or False. If a condition is False, the object is considered invalid. Because conditions are written inside a data type, they can reference attributes directly.

Conditions are usually placed at the end of a type definition and include:

  • a name
  • a plain-text description - optional
  • an operator that applies to the type's attributes and returns a booleanBoolean Data type with only two values (yes/no, on/off etc).

Syntax

condition <ConditionName>: 
<logic_expression>

Example

Checking if a percentage is within a valid range:

type ConstituentWeight:
basketPercentage number (0..1)
condition BasketPercentage:
if basketPercentage exists
then basketPercentage >= 0.0 and basketPercentage <= 1.0

2.1 Choice conditions

Sometimes, the validity of one attribute depends on another. Rune provides ‘choice’ rules to handle these relationships without writing complex booleanBoolean Data type with only two values (yes/no, on/off etc). logic. A choice rule defines a mutual exclusion constraint between attributes. There are two main types:

  • Optional choice: At most one attribute can be present (0 or 1).
  • Required choice: Exactly one attribute must be present (1 only).

Syntax

<choiceType> choice <attribute1>, <attribute2>, ...

Note: All attributes in a choice rule must have a lower cardinalityCardinality The number of elements in a set or other grouping, as a property of that grouping. of 0.

Example

In a NaturalPerson type, you might have an optional choice between a middleName or an initial:

condition NameChoice:
optional choice middleName, initial

2.2 The one-of shortcut

If you want a rule where exactly one attribute from the entire list must be present, you can use the one-of shorthand. This is much faster than listing every single attribute in a choice rule.

Example

type PeriodRange:
lowerBound PeriodBound (0..1)
upperBound PeriodBound (0..1)
condition: one-of // Either lowerBound or upperBound must exist, but not both.