Interro::Validations::Result(T)
Inherits Struct / Value / Object
The entrypoint into validating your objects is to instantiate a
Result(T), which you then call validation methods on. When you're
finished calling validations, you call valid with a block. That block
will execute if your values pass all validations, returning the value
in the block (which must be the T type of the Result), or an
Interro::Validations::Failure object, which contains the validation
errors for the given inputs.
struct UserQuery < Interro::QueryBuilder(User)
def create(*, name : String, email : String, team : Team, role : User::Role)
Result(User).new
.validate_presence(name: name, email: email)
.validate_uniqueness("email") { where(email: email).any? }
.validate_format(/\w@\w/, email: email, failure_message: "must be a valid email address")
.valid do
insert(
name: name,
email: email,
team_id: team.id,
role: role.value,
)
end
end
end
Constructors
Instance methods
Combine the errors of two different Result instances. The T types do not have to match.
Execute the block given if all validations have passed, otherwise return
a Failure containing all of the validation errors.
Validate a block returns truthy, failing validation with the given message if it returns falsy.
struct Post < Interro::QueryBuilder(T)
table "posts"
def create(*, title : String, body : String, by author : User, published : Bool, tags : Array(String)? = nil) : Post | Failure
Result(Post).new
.validate("tags", "must be populated for published posts") do
!published || tags.try(&.any?)
end
.valid do
published_at = Time.utc if published
insert(
title: title,
body: body,
author_id: author.id,
published_at: published_at,
tags: tags,
)
end
end
end
Validate a block returns truthy, failing validation with the given message if it returns falsy.
struct Post < Interro::QueryBuilder(T)
table "posts"
def create(*, title : String, body : String, by author : User, published : Bool, tags : Array(String)? = nil) : Post | Failure
Result(Post).new
.validate("published posts must have tags") do
!published || tags.try(&.any?)
end
.valid do
published_at = Time.utc if published
insert(
title: title,
body: body,
author_id: author.id,
published_at: published_at,
tags: tags,
)
end
end
end
Validate that value matches the expected format in the Regex, using
the attribute name specified in name and a default failure_message.
Result(User).new
.validate_format("email", email, /\w@\w/, failure_message: "must be a valid email address")
Validate that value matches the expected format in the Regex. This
method does not infer a name, so a custom failure_message must be
provided.
Result(User).new
.validate_format(email, /\w@\w/, failure_message: "Email must be a valid email address (user@domain.tld)")
Validate that all of the attributes match the expected format in the
Regex.
Result(User).new
.validate_format(/\w@\w/, email: email)
Validate whether all of the values are present by calling .presence
on them.
Result(Post).new
.validate_presence(title: title, body: body)
Validate that value is of the expected size range. Value can be any object that responds to #size.
Result(User).new
.validate_size("username", username, 2..64, "characters")
Validate that the given attribute is unique by executing a block that returns truthy if any other objects exist with that attribute.
Result(User).new
.validate_uniqueness("email") { where(email: email).any? }
Validate that the given attribute is unique by executing a block that returns truthy if any other objects exist with that attribute.
Result(User).new
.validate_uniqueness(message: "That email has already been taken") { where(email: email).any? }