Introduction
Lutaml::Model provides built-in validation to ensure your data meets requirements. This tutorial covers the essential validation features.
Validation methods
Lutaml::Model provides two validation methods:
validate-
Returns an array of validation errors (silent validation)
validate!-
Raises
ValidationErrorwith all errors (forceful validation)
Required attributes
Mark attributes as required using required: true:
Example 1. Requiring an attribute
class Person < Lutaml::Model::Serializable
attribute :name, :string, required: true
attribute :email, :string
end
# This works
person = Person.new(name: "John")
person.validate
# => []
# This fails - name is required
person = Person.new(email: "john@example.com")
person.validate
# => [#<Lutaml::Model::RequiredAttributeMissingError: Missing required attribute: name>]
person.validate!
# => Lutaml::Model::ValidationError: Missing required attribute: nameCollection size validation
Validate collection sizes using range constraints:
Example 2. Collection size constraints
class Workshop < Lutaml::Model::Serializable
attribute :title, :string
attribute :students, :string, collection: 1..20 # Min 1, max 20
key_value do
map 'title', to: :title
map 'students', to: :students
end
end
# Valid - 2 students
workshop = Workshop.new(title: "Pottery 101", students: ["Alice", "Bob"])
workshop.validate
# => []
# Invalid - 0 students (minimum is 1)
empty_workshop = Workshop.new(title: "Empty", students: [])
empty_workshop.validate
# => [#<Lutaml::Model::CollectionCountOutOfRangeError: students count is 0, must be between 1 and 20>]Enumeration validation
Restrict values to a fixed set using values::
Example 3. Enumeration validation
class Glaze < Lutaml::Model::Serializable
attribute :finish, :string, values: ["Matte", "Glossy", "Satin"]
end
# Valid value
glaze = Glaze.new(finish: "Matte")
glaze.validate
# => []
# Invalid value
bad_glaze = Glaze.new(finish: "Sparkly")
bad_glaze.validate
# => [#<Lutaml::Model::InvalidValueError: Invalid value for attribute 'finish'>]Pattern validation
Validate strings against regex patterns using pattern::
Example 4. Pattern validation for strings
class Product < Lutaml::Model::Serializable
attribute :sku, :string, pattern: /\A[A-Z]{3}-\d{4}\z/ # Format: ABC-1234
attribute :hex_color, :string, pattern: /\A#[0-9A-Fa-f]{6}\z/
key_value do
map 'sku', to: :sku
map 'color', to: :hex_color
end
end
# Valid patterns
product = Product.new(sku: "ABC-1234", hex_color: "#FF5733")
product.validate
# => []
# Invalid pattern
bad_product = Product.new(sku: "abc-1234", hex_color: "#FFF")
bad_product.validate
# => [
# #<Lutaml::Model::InvalidValueError: Invalid value for attribute 'sku'>,
# #<Lutaml::Model::InvalidValueError: Invalid value for attribute 'hex_color'>
# ]Choice validation
The choice directive validates that attribute counts fall within specified ranges:
Example 5. Choice validation
class Contact < Lutaml::Model::Serializable
# Must have 1-2 contact methods
choice(min: 1, max: 2) do
attribute :email, :string
attribute :phone, :string
end
xml do
root "contact"
map_element "email", to: :email
map_element "phone", to: :phone
end
end
# Valid - 1 contact method
contact1 = Contact.new(email: "john@example.com")
contact1.validate
# => []
# Valid - 2 contact methods
contact2 = Contact.new(email: "john@example.com", phone: "555-1234")
contact2.validate
# => []
# Invalid - 0 contact methods
contact3 = Contact.new
contact3.validate
# => [#<Lutaml::Model::ChoiceLowerBoundError: Attribute count is less than lower bound>]Combining validations
You can combine multiple validation types:
Example 6. Multiple validation rules
class Student < Lutaml::Model::Serializable
attribute :name, :string, required: true
attribute :age, :integer
attribute :grade, :string, values: ["A", "B", "C", "D", "F"]
attribute :courses, :string, collection: 1..8
key_value do
map 'name', to: :name
map 'age', to: :age
map 'grade', to: :grade
map 'courses', to: :courses
end
end
# Valid student
student = Student.new(
name: "Alice",
age: 16,
grade: "A",
courses: ["Math", "Science"]
)
student.validate
# => []
# Multiple validation errors
bad_student = Student.new(
grade: "F+", # Not in values list
courses: [] # Below minimum count of 1
# name missing (required)
)
bad_student.validate
# => [
# #<Lutaml::Model::RequiredAttributeMissingError: Missing required attribute: name>,
# #<Lutaml::Model::InvalidValueError: Invalid value for attribute 'grade'>,
# #<Lutaml::Model::CollectionCountOutOfRangeError: courses count is 0, must be between 1 and 8>
# ]