Skip to main content

RuniqueForm

Trait RuniqueForm 

Source
pub trait RuniqueForm:
    Sized
    + Send
    + Sync {
Show 21 methods // Required methods fn register_fields(form: &mut Forms); fn from_form(form: Forms) -> Self; fn get_form(&self) -> &Forms; fn get_form_mut(&mut self) -> &mut Forms; // Provided methods fn cleaned_string(&self, name: &str) -> Option<String> { ... } fn cleaned_i32(&self, name: &str) -> Option<i32> { ... } fn cleaned_i64(&self, name: &str) -> Option<i64> { ... } fn cleaned_u32(&self, name: &str) -> Option<u32> { ... } fn cleaned_u64(&self, name: &str) -> Option<u64> { ... } fn cleaned_f32(&self, name: &str) -> Option<f32> { ... } fn cleaned_f64(&self, name: &str) -> Option<f64> { ... } fn cleaned_bool(&self, name: &str) -> Option<bool> { ... } fn clear(&mut self) { ... } fn clean_field<'life0, 'life1, 'async_trait>( &'life0 mut self, name: &'life1 str, ) -> Pin<Box<dyn Future<Output = bool> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait { ... } fn clean<'life0, 'async_trait>( &'life0 mut self, ) -> Pin<Box<dyn Future<Output = Result<(), StrMap>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait { ... } fn is_valid<'life0, 'async_trait>( &'life0 mut self, ) -> Pin<Box<dyn Future<Output = bool> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait { ... } fn save_txn<'life0, 'life1, 'async_trait>( &'life0 mut self, _txn: &'life1 DatabaseTransaction, ) -> Pin<Box<dyn Future<Output = Result<(), DbErr>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait { ... } fn save<'life0, 'life1, 'async_trait>( &'life0 mut self, db: &'life1 DatabaseConnection, ) -> Pin<Box<dyn Future<Output = Result<(), DbErr>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait { ... } fn database_error(&mut self, err: &DbErr) { ... } fn build(tera: ATera, csrf_token: &str) -> Self { ... } fn build_with_data<'life0, 'life1, 'async_trait>( raw_data: &'life0 StrMap, tera: ATera, csrf_token: &'life1 str, method: Method, ) -> Pin<Box<dyn Future<Output = Self> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait { ... }
}
Expand description

Main trait for typed forms with validation and saving

§Formulaire basé modèle avec #[form(...)] et impl_form_access!(model)

La macro #[form(...)] génère la struct et impl ModelForm. Le dev écrit impl RuniqueForm avec impl_form_access!(model) pour brancher les champs du modèle.

use runique::prelude::*;

#[form(schema = user_schema, fields = [username, email, password])]
pub struct RegisterForm;

impl RuniqueForm for RegisterForm {
    impl_form_access!(model);
}

§Avec validation métier

#[async_trait] requis uniquement quand on override une méthode async :

use runique::prelude::*;

#[form(schema = user_schema, fields = [username, email, password])]
pub struct RegisterForm;

#[async_trait]
impl RuniqueForm for RegisterForm {
    impl_form_access!(model);

    async fn clean(&mut self) -> Result<(), StrMap> {
        let mut errors = StrMap::new();
        if self.get_string("username").len() < 3 {
            errors.insert("username".to_string(), "Minimum 3 caractères".to_string());
        }
        if !self.get_string("email").contains('@') {
            errors.insert("email".to_string(), "Email invalide".to_string());
        }
        if errors.is_empty() { Ok(()) } else { Err(errors) }
    }
}

§Validation métier : clean_field, clean et save

use runique::prelude::*;
use runique::forms::{RuniqueForm, Forms};
use runique::forms::fields::text::TextField;
use sea_orm::{DatabaseTransaction, DbErr, Set};

pub struct ChangePasswordForm {
    form: Forms,
}

#[async_trait]
impl RuniqueForm for ChangePasswordForm {
    impl_form_access!();

    fn register_fields(form: &mut Forms) {
        form.field(&TextField::password("password").label("Nouveau mot de passe").required());
        form.field(&TextField::password("confirm").label("Confirmation").required());
    }

    /// Validation par champ — appelée pour chaque champ par is_valid()
    async fn clean_field(&mut self, name: &str) -> bool {
        match name {
            "password" => {
                let pwd = self.get_form().get_string("password");
                if pwd.len() < 8 {
                    if let Some(field) = self.get_form_mut().fields.get_mut("password") {
                        field.set_error("Le mot de passe doit faire au moins 8 caractères".to_string());
                    }
                    return false;
                }
                true
            }
            _ => true,
        }
    }

    /// Validation globale inter-champs — appelée après tous les clean_field()
    async fn clean(&mut self) -> Result<(), StrMap> {
        let password = self.get_form().get_string("password");
        let confirm  = self.get_form().get_string("confirm");

        if password != confirm {
            let mut errors = StrMap::new();
            errors.insert("confirm".to_string(), "Les mots de passe ne correspondent pas".to_string());
            return Err(errors);
        }

        Ok(())
    }

    /// Sauvegarde dans une transaction — appelée par save()
    async fn save_txn(&mut self, _txn: &DatabaseTransaction) -> Result<(), DbErr> {
        // let hashed = hash(&self.get_form().get_string("password")).unwrap_or_default();
        // UserActiveModel { password: Set(hashed), ..Default::default() }.update(_txn).await?;
        Ok(())
    }
}

Required Methods§

Source

fn register_fields(form: &mut Forms)

Source

fn from_form(form: Forms) -> Self

Source

fn get_form(&self) -> &Forms

Source

fn get_form_mut(&mut self) -> &mut Forms

Provided Methods§

Source

fn cleaned_string(&self, name: &str) -> Option<String>

StringNone if the field is unknown or empty.

Source

fn cleaned_i32(&self, name: &str) -> Option<i32>

i32None if unknown, empty, or not parseable.

Source

fn cleaned_i64(&self, name: &str) -> Option<i64>

i64None if unknown, empty, or not parseable.

Source

fn cleaned_u32(&self, name: &str) -> Option<u32>

u32None if unknown, empty, or not parseable.

Source

fn cleaned_u64(&self, name: &str) -> Option<u64>

u64None if unknown, empty, or not parseable.

Source

fn cleaned_f32(&self, name: &str) -> Option<f32>

f32 — handles ,.. None if unknown, empty, or not parseable.

Source

fn cleaned_f64(&self, name: &str) -> Option<f64>

f64 — handles ,.. None if unknown, empty, or not parseable.

Source

fn cleaned_bool(&self, name: &str) -> Option<bool>

booltrue for "true", "1", "on" (case-insensitive). Returns None if the field does not exist in the form. Note: fill() normalizes unchecked checkboxes/radios to "false", so this method always returns Some(_) for a submitted boolean field.

Source

fn clear(&mut self)

Clears all form values (except CSRF).

Source

fn clean_field<'life0, 'life1, 'async_trait>( &'life0 mut self, name: &'life1 str, ) -> Pin<Box<dyn Future<Output = bool> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Source

fn clean<'life0, 'async_trait>( &'life0 mut self, ) -> Pin<Box<dyn Future<Output = Result<(), StrMap>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Source

fn is_valid<'life0, 'async_trait>( &'life0 mut self, ) -> Pin<Box<dyn Future<Output = bool> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Source

fn save_txn<'life0, 'life1, 'async_trait>( &'life0 mut self, _txn: &'life1 DatabaseTransaction, ) -> Pin<Box<dyn Future<Output = Result<(), DbErr>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Default atomic wrapper: opens a transaction and calls save_txn.

  • if save_txn returns Err -> automatic rollback
  • otherwise -> commit
Source

fn save<'life0, 'life1, 'async_trait>( &'life0 mut self, db: &'life1 DatabaseConnection, ) -> Pin<Box<dyn Future<Output = Result<(), DbErr>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Atomic wrapper: explicit transaction (avoids the ’static futures trap)

Source

fn database_error(&mut self, err: &DbErr)

Source

fn build(tera: ATera, csrf_token: &str) -> Self

Source

fn build_with_data<'life0, 'life1, 'async_trait>( raw_data: &'life0 StrMap, tera: ATera, csrf_token: &'life1 str, method: Method, ) -> Pin<Box<dyn Future<Output = Self> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§