ruskit 0.1.5

A modern web framework for Rust inspired by Laravel
Documentation
{% extends "docs_base.html" %}

{% block title %}Validation - Ruskit Documentation{% endblock %}

{% block content %}
<div class="prose prose-slate max-w-none">
    <h1>Validation</h1>
    
    <p>Ruskit provides a robust validation system to ensure that incoming data meets your application's requirements. The validation system is easy to use and highly customizable.</p>

    <h2>Basic Validation</h2>
    <p>Use the <code>Validate</code> derive macro to add validation rules to your DTOs:</p>

    <pre><code class="language-rust">use validator::Validate;
use serde::Deserialize;

#[derive(Deserialize, Validate)]
pub struct CreateUserRequest {
    #[validate(length(min = 3, max = 50))]
    pub name: String,

    #[validate(email)]
    pub email: String,

    #[validate(length(min = 8))]
    pub password: String,

    #[validate(range(min = 18, max = 150))]
    pub age: u32,
}</code></pre>

    <h2>Built-in Validation Rules</h2>
    <p>Ruskit includes many built-in validation rules:</p>

    <h3>String Validation</h3>
    <pre><code class="language-rust">#[derive(Validate)]
pub struct StringValidation {
    #[validate(length(min = 5, max = 20))]
    pub username: String,

    #[validate(email)]
    pub email: String,

    #[validate(url)]
    pub website: String,

    #[validate(contains = "hello")]
    pub greeting: String,

    #[validate(regex = "^[a-zA-Z]+$")]
    pub letters_only: String,
}</code></pre>

    <h3>Numeric Validation</h3>
    <pre><code class="language-rust">#[derive(Validate)]
pub struct NumericValidation {
    #[validate(range(min = 18, max = 100))]
    pub age: u32,

    #[validate(multiple_of = 5)]
    pub multiple: i32,

    #[validate(custom = "validate_positive")]
    pub positive: f64,
}</code></pre>

    <h3>Collection Validation</h3>
    <pre><code class="language-rust">#[derive(Validate)]
pub struct CollectionValidation {
    #[validate(length(min = 1, max = 10))]
    pub tags: Vec<String>,

    #[validate]
    pub items: Vec<ValidatedItem>,

    #[validate(required_if = "condition")]
    pub optional_field: Option<String>,
}</code></pre>

    <h2>Custom Validation Rules</h2>
    <p>You can create custom validation rules using functions:</p>

    <pre><code class="language-rust">fn validate_positive(value: &f64) -> Result<(), ValidationError> {
    if *value > 0.0 {
        Ok(())
    } else {
        Err(ValidationError::new("must be positive"))
    }
}

#[derive(Validate)]
pub struct CustomValidation {
    #[validate(custom = "validate_positive")]
    pub amount: f64,
}</code></pre>

    <h2>Using Validation in Controllers</h2>
    <p>Validate request data in your controllers:</p>

    <pre><code class="language-rust">pub async fn create_user(
    Json(data): Json<CreateUserRequest>
) -> Result<Response, AppError> {
    // Validate the request data
    data.validate()?;

    // Process the validated data
    let user = User::create(data).await?;

    Ok(Json(user).into_response())
}</code></pre>

    <h2>Nested Validation</h2>
    <p>Validate nested structures:</p>

    <pre><code class="language-rust">#[derive(Validate)]
pub struct Address {
    #[validate(length(min = 5))]
    pub street: String,
    
    #[validate(length(min = 2))]
    pub city: String,
    
    #[validate(regex = "^[0-9]{5}$")]
    pub zip: String,
}

#[derive(Validate)]
pub struct CreateUserRequest {
    #[validate]
    pub name: String,
    
    #[validate]
    pub address: Address,
}</code></pre>

    <h2>Error Handling</h2>
    <p>Handle validation errors gracefully:</p>

    <pre><code class="language-rust">impl From<ValidationErrors> for AppError {
    fn from(errors: ValidationErrors) -> Self {
        AppError::ValidationError(errors)
    }
}

pub async fn create_user(
    Json(data): Json<CreateUserRequest>
) -> Result<Response, AppError> {
    match data.validate() {
        Ok(_) => {
            // Process valid data
            let user = User::create(data).await?;
            Ok(Json(user).into_response())
        }
        Err(errors) => {
            // Return validation errors
            Err(AppError::ValidationError(errors))
        }
    }
}</code></pre>

    <h2>Best Practices</h2>
    <ul>
        <li>Validate data as early as possible in the request lifecycle</li>
        <li>Use appropriate validation rules for each field</li>
        <li>Provide clear error messages for validation failures</li>
        <li>Consider using custom validation rules for complex requirements</li>
        <li>Handle validation errors consistently across your application</li>
    </ul>
</div>
{% endblock %}