-
Notifications
You must be signed in to change notification settings - Fork 1
Verification
Verification<T> is a value bound to a ValidationScope. It is the primary surface for chaining validation rules and
is created by calling verify on a scope:
validateCollecting {
val verification: Verification<String> = verify(user::name)
}In practice, you rarely hold a reference to it — rules are chained directly:
validateCollecting {
verify(user::name).notBlank().minLength(3)
}The scope property on Verification<T> carries the active ValidationContext, so any rules applied to it have access
to path and other contextual information. The value property holds the value being validated.
takeIfNotNull narrows a Verification<T?> to Verification<T> when the value is not null, returning null
otherwise. This enables safe chaining of rules that expect a non-null type:
validateCollecting {
verify(user::middleName)
.takeIfNotNull()
?.minLength(2)
?.maxLength(50)
}If middleName is null, the chain short-circuits and no rules are applied. If it is not null, the rules run
normally on the unwrapped value.
each validates every element of an iterable, automatically appending each element's index to the validation path. It
works on any Iterable<T> — collections being the most common case:
validateCollecting {
verify(order::items).each { item ->
verify(item::name).notBlank()
verify(item::price).greaterThan(0.0)
}
}Each element is validated in its own indexed scope. If the third item fails, the violation path will reflect index 2.
each returns this, so you can chain further rules on the iterable itself after iterating its elements:
validateCollecting {
verify(order::items)
.minSize(1)
.each { item ->
verify(item::name).notBlank()
verify(item::price).greaterThan(0.0)
}
}Rules in KVerify are extension functions on Verification<T>. The built-in rules are all defined this way, and your own
rules follow the same pattern. This is covered in depth on the Rule page.
- Rule — learn how to write your own rules as extension functions and more