Démarrage
Cette documentation couvre ivo pour Rust v0.6.0.
Les schémas se déclarent, ils ne se construisent pas de façon impérative : une seule macro
d'attribut, #[ivo_schema(...)], prend un module contenant vos déclarations de champs et génère
les structs d'entrée/sortie, leurs équivalents partiels/erreurs, ainsi qu'un modèle typé et
spécifique au schéma avec des méthodes create/update/delete.
Installation
cargo add ivo
Démarrage rapide
use chrono::{DateTime, Utc};
use ivo::ivo_schema;
type Timestamp = DateTime<Utc>;
#[ivo_schema(
input(PostInput, derive(Debug, Clone, PartialEq)),
output(Post, derive(Debug, Clone, PartialEq))
)]
mod post_schema {
use super::Timestamp;
use chrono::Utc;
struct Fields {
#[constant(1)]
pub id: i32,
#[created_at]
pub created_at: Timestamp,
#[updated_at]
pub updated_at: Timestamp,
#[required]
#[validate(|title: String, _, _| {
if title.trim().len() < 3 {
return Err(("title must be at least 3 characters long".into(), None));
}
Ok(Some(title.trim().to_string()))
})]
pub title: String,
#[lax(String::new())]
pub body: String,
}
#[timestamps(|| Utc::now())]
const _: () = ();
}
use post_schema::{PartialPostInput, PostModel};
fn main() {
let (post, _ctx_options) = PostModel
.create(
PartialPostInput {
title: Some("Hello, ivo!".into()),
body: Some("My first post.".into()),
},
(), // ctx_options -- `()` quand le schéma n'en déclare aucune
)
.unwrap();
println!("{:#?}", post); // -> Post { id, created_at, updated_at, title, body }
let (updated, _ctx_options) = PostModel
.update(
post,
PartialPostInput {
title: None,
body: Some("Edited.".into()),
},
(),
)
.unwrap();
println!("{:#?}", updated); // -> PartialPost { body: Some("Edited."), .. le reste à None }
}
input(...)nomme la struct d'entrée générée et est toujours obligatoire ;output(...)nomme la struct de sortie et n'est obligatoire que lorsque le schéma a des champs exclusifs à l'entrée (#[ivo_virtual]) ou à la sortie (#[constant],#[depends_on(...)], horodatages). Un schéma ne contenant que des champs#[required]/#[lax]peut omettreoutput(...)entièrement et utiliser une seule struct pour les deux.derive(...)ajoute des dérivations à la struct générée ;derive_partial(...)les ajoute à son équivalent partiel (par ex. pour dériverSerialize/Deserializepour le transport réseau).- La macro génère une valeur unité
{OutputName}Model(ou{InputName}Modelpour un schéma à une seule struct) --post_schema::PostModel.create(...)fonctionne directement, sans::new(). create/update/deletene sontasyncque si au moins un gestionnaire qu'ils invoquent est asynchrone -- sinon, la méthode générée est purement synchrone, sans imposer de dépendance à un runtime.create/updateretournent(data, ctx_options)lorsque le schéma n'a aucun gestionnaireon_success/on_failuresur ce chemin, comme ci-dessus -- voir Cycles de vie pour la forme à 3 éléments retournée quand ce n'est pas le cas.
Définir un schéma
Les champs d'un schéma appartiennent à l'une de six catégories - voir chacune pour les règles et un exemple exécutable :
Voir Validateurs pour le fonctionnement de #[validate]/#[re_validate], et
Cycles de vie pour #[on_success]/#[on_failure]/#[on_delete].
Options du schéma
Le comportement groupé et transversal aux champs s'attache à un élément const _: () = ();
anonyme à l'intérieur du module du schéma, et non enchaîné à l'appel de la macro -- voir
Options du schéma pour ignore, ignore_update, required, post_validate,
on_success, on_delete et timestamps, chacune avec un exemple exécutable.
Options de contexte personnalisées
ctx_options(VotreType) fait transiter une valeur de votre propre type (injection de
dépendances, cache, données propres à la requête, ...) à travers chaque gestionnaire d'un appel
create/update. Voir
Options du schéma - Options de contexte personnalisées,
ou la démo complète dans
examples/main_demo.
ErrorSanitizer personnalisé
Le payload par défaut retourné pour les opérations échouées a la signature suivante :
type DefaultFieldErrorMetadata = ();
struct FieldError<Metadata: Clone = DefaultFieldErrorMetadata> {
pub reason: String,
pub metadata: Option<Metadata>,
}
type IvoErrorPayload<Metadata> = HashMap<String, FieldError<Metadata>>;
Pour personnaliser ce payload, fournissez une implémentation du trait IvoErrorSanitizer via
error_sanitizer(VotreSanitizer) -- voir
Options du schéma - Payloads d'erreur personnalisés.
Référence de l'API
La documentation narrative ci-dessus couvre les concepts de haut niveau. Pour la référence exhaustive de l'API générée (types, fonctions, macros dérivées), voir :
- docs.rs/crate/ivo — rustdoc hébergé pour le crate publié.
- crates.io/crates/ivo — page du registre de crates (versions, dépendances, README).
- rustdoc local — exécutez
cargo doc --no-deps --opendepuis le répertoirers/pour parcourir la même référence générée localement.