Applicare una mutation in una struct in Rust e sqlx

Mattepuffo's logo
Applicare una mutation in una struct in Rust e sqlx

Applicare una mutation in una struct in Rust e sqlx

Forse il termine mutation non è tra i più corretti, ma rende l'idea.

In pratica ho una struct in Rust, e quando inserisco i valori nel db voglio fare il trim delle stringhe (ma si può applicare anche ad altre trasformazioni ovviamente).

Ci sono ovviamente vari modi per farlo, e noi vediamo quello di usare una impl.

Quindi ad esempio:

#[derive(Serialize, FromRow, Deserialize)]
pub struct AnagraficaAttributo {
    pub attr_anag: i32,
    pub attr_chiave: String,
    pub attr_valore: String,
    pub attr_data_aggiunta: NaiveDateTime,
    pub attr_data_modifica: NaiveDateTime,
}

impl AnagraficaAttributo {
    pub fn trimmed(mut self) -> Self {
        self.attr_chiave = self.attr_valore.trim().to_string();
        self.attr_valore = self.attr_valore.trim().to_string();
        self
    }
}

Ma se una struct contenesse dei campi Option?

Possiamo fare così:

#[derive(Serialize, FromRow, Deserialize)]
pub struct Anagrafica {
    pub ag_id: Option<i32>,
    pub ag_denominazione: Option<String>,
    pub ag_alias: Option<String>,
    pub ag_email: Option<String>,
    pub ag_piva: Option<String>,
    pub ag_cf: Option<String>,
    pub ag_pec: Option<String>,
    pub ag_codice_ident: Option<String>,
    pub ag_telefono: Option<String>,
    pub ag_indirizzo: Option<String>,
    pub ag_cap: Option<String>,
    pub ag_citta: Option<String>,
    pub ag_paese: Option<String>,
    pub ag_web: Option<String>,
    pub ag_logo: Option<String>,
    pub ag_note: Option<String>,
    pub ag_utente_fk: i32,
    pub ag_provincia: Option<String>,
    pub ag_data_aggiunta: Option<NaiveDateTime>,
    pub ag_data_modifica: Option<NaiveDateTime>,
}

impl Anagrafica {
    pub fn trimmed(mut self) -> Self {
        fn trim_opt(s: Option<String>) -> Option<String> {
            s.map(|v| v.trim().to_string())
        }

        self.ag_denominazione = trim_opt(self.ag_denominazione);
        self.ag_alias = trim_opt(self.ag_alias);
        self.ag_email = trim_opt(self.ag_email);
        self.ag_piva = trim_opt(self.ag_piva);
        self.ag_cf = trim_opt(self.ag_cf);
        self.ag_pec = trim_opt(self.ag_pec);
        self.ag_codice_ident = trim_opt(self.ag_codice_ident);
        self.ag_telefono = trim_opt(self.ag_telefono);
        self.ag_indirizzo = trim_opt(self.ag_indirizzo);
        self.ag_cap = trim_opt(self.ag_cap);
        self.ag_citta = trim_opt(self.ag_citta);
        self.ag_paese = trim_opt(self.ag_paese);
        self.ag_web = trim_opt(self.ag_web);
        self.ag_logo = trim_opt(self.ag_logo);
        self.ag_note = trim_opt(self.ag_note);
        self.ag_provincia = trim_opt(self.ag_provincia);
        self
    }
}

Vi posto anche un service per farvi capire come viene applicata:

pub async fn save(state: &AppState, input: Anagrafica) -> Result<i32, Error> {
    // APPLICAZIONE MUTATION
    let input = input.trimmed();

    if let Some(id) = input.ag_id {
        if id > 0 {
            sqlx::query(
                r#"
                UPDATE anag_generali SET
                    ag_denominazione = ?, ag_email = ?, ag_piva = ?, ag_cf = ?, ag_pec = ?,
                    ag_codice_ident = ?, ag_telefono = ?, ag_indirizzo = ?, ag_cap = ?, ag_citta = ?,
                    ag_paese = ?, ag_web = ?, ag_logo = ?, ag_note = ?, ag_provincia = ?,
                    ag_data_modifica = NOW()
                WHERE ag_id = ?
                "#,
            )
            .bind(input.ag_denominazione)
            .bind(input.ag_email)
            .bind(input.ag_piva)
            .bind(input.ag_cf)
            .bind(input.ag_pec)
            .bind(input.ag_codice_ident)
            .bind(input.ag_telefono)
            .bind(input.ag_indirizzo)
            .bind(input.ag_cap)
            .bind(input.ag_citta)
            .bind(input.ag_paese)
            .bind(input.ag_web)
            .bind(input.ag_logo)
            .bind(input.ag_note)
            .bind(input.ag_provincia)
            .bind(id)
            .execute(&state.pool)
            .await?;

            return Ok(id);
        }
    }

    let res = sqlx::query(
        r#"
          INSERT INTO anag_generali (
              ag_denominazione, ag_email, ag_piva, ag_cf, ag_pec,
              ag_codice_ident, ag_telefono, ag_indirizzo, ag_cap, ag_citta,
              ag_paese, ag_web, ag_logo, ag_note, ag_provincia,
              ag_utente_fk, ag_data_aggiunta, ag_data_modifica
          )
          VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW(), NOW())
          "#,
    )
    .bind(input.ag_denominazione)
    .bind(input.ag_email)
    .bind(input.ag_piva)
    .bind(input.ag_cf)
    .bind(input.ag_pec)
    .bind(input.ag_codice_ident)
    .bind(input.ag_telefono)
    .bind(input.ag_indirizzo)
    .bind(input.ag_cap)
    .bind(input.ag_citta)
    .bind(input.ag_paese)
    .bind(input.ag_web)
    .bind(input.ag_logo)
    .bind(input.ag_note)
    .bind(input.ag_provincia)
    .bind(input.ag_utente_fk)
    .execute(&state.pool)
    .await?;

    Ok(res.last_insert_id() as i32)
}

Enjoy!


Condividi

Commentami!