Skip to main content
Spelling and grammar
Source Link
Toby Speight
  • 88.3k
  • 14
  • 104
  • 327

I just started learning RUSTRust, and try to implement in a pet project function like Django's get_or_create.

Now my implementation looks too verbose,verbose[ I hope that rust can be more neatneater. Therefore, how can I implement this function in less verbose way? Probable thereThere is probably a way to shorten nested match constructions below?

use log::warn;

use diesel::prelude::*;
use diesel::result;

use crate::db::{get_connection, PgPool};
use crate::models::{NewUser, User};

pub fn get_or_create_user(pool: &PgPool, email: &str) -> User {
    use crate::schema::users;

    let new_user = NewUser { email };
    let mut conn = get_connection(pool);

    let result = diesel::insert_into(users::table)
        .values(&new_user)
        .get_result(&mut conn);

    match result {
        Ok(user) => return user,
        Err(err) => match err {
            result::Error::DatabaseError(err_kind, info) => match err_kind {
                result::DatabaseErrorKind::UniqueViolation => {
                    warn!(
                        "{:?} is already exists. Info: {:?}. Skipping.",
                        new_user, info
                    );
                    // another query to DB to get existing user by email
                    let user = user_by_email(pool, new_user.email);
                    return user;
                }
                _ => {
                    panic!("Database error: {:?}", info);
                }
            },
            _ => {
                // TODO: decide how to deal with unexpected errors
                return User {
                    id: 0,
                    email: "".into(),
                };
            }
        },
    }
}

pub fn user_by_email(pool: &PgPool, user_email: &str) -> User {
    use crate::schema::users::dsl::*;

    let mut conn = get_connection(pool);

    let user = crate::schema::users::dsl::users
        .filter(email.eq(user_email))
        .first(&mut conn)
        .unwrap();
    return user;
}
```

I just started learning RUST, and try to implement in a pet project function like Django's get_or_create.

Now my implementation looks too verbose, I hope that rust can be more neat. Therefore, how can I implement this function in less verbose way? Probable there is a way to shorten nested match constructions below?

use log::warn;

use diesel::prelude::*;
use diesel::result;

use crate::db::{get_connection, PgPool};
use crate::models::{NewUser, User};

pub fn get_or_create_user(pool: &PgPool, email: &str) -> User {
    use crate::schema::users;

    let new_user = NewUser { email };
    let mut conn = get_connection(pool);

    let result = diesel::insert_into(users::table)
        .values(&new_user)
        .get_result(&mut conn);

    match result {
        Ok(user) => return user,
        Err(err) => match err {
            result::Error::DatabaseError(err_kind, info) => match err_kind {
                result::DatabaseErrorKind::UniqueViolation => {
                    warn!(
                        "{:?} is already exists. Info: {:?}. Skipping.",
                        new_user, info
                    );
                    // another query to DB to get existing user by email
                    let user = user_by_email(pool, new_user.email);
                    return user;
                }
                _ => {
                    panic!("Database error: {:?}", info);
                }
            },
            _ => {
                // TODO: decide how to deal with unexpected errors
                return User {
                    id: 0,
                    email: "".into(),
                };
            }
        },
    }
}

pub fn user_by_email(pool: &PgPool, user_email: &str) -> User {
    use crate::schema::users::dsl::*;

    let mut conn = get_connection(pool);

    let user = crate::schema::users::dsl::users
        .filter(email.eq(user_email))
        .first(&mut conn)
        .unwrap();
    return user;
}
```

I just started learning Rust, and try to implement a function like Django's get_or_create.

Now my implementation looks too verbose[ I hope that rust can be neater. Therefore, how can I implement this function in less verbose way? There is probably a way to shorten nested match constructions below?

use log::warn;

use diesel::prelude::*;
use diesel::result;

use crate::db::{get_connection, PgPool};
use crate::models::{NewUser, User};

pub fn get_or_create_user(pool: &PgPool, email: &str) -> User {
    use crate::schema::users;

    let new_user = NewUser { email };
    let mut conn = get_connection(pool);

    let result = diesel::insert_into(users::table)
        .values(&new_user)
        .get_result(&mut conn);

    match result {
        Ok(user) => return user,
        Err(err) => match err {
            result::Error::DatabaseError(err_kind, info) => match err_kind {
                result::DatabaseErrorKind::UniqueViolation => {
                    warn!(
                        "{:?} is already exists. Info: {:?}. Skipping.",
                        new_user, info
                    );
                    // another query to DB to get existing user by email
                    let user = user_by_email(pool, new_user.email);
                    return user;
                }
                _ => {
                    panic!("Database error: {:?}", info);
                }
            },
            _ => {
                // TODO: decide how to deal with unexpected errors
                return User {
                    id: 0,
                    email: "".into(),
                };
            }
        },
    }
}

pub fn user_by_email(pool: &PgPool, user_email: &str) -> User {
    use crate::schema::users::dsl::*;

    let mut conn = get_connection(pool);

    let user = crate::schema::users::dsl::users
        .filter(email.eq(user_email))
        .first(&mut conn)
        .unwrap();
    return user;
}
Source Link

Implement get_or_create() with Rust and Diesel

I just started learning RUST, and try to implement in a pet project function like Django's get_or_create.

Now my implementation looks too verbose, I hope that rust can be more neat. Therefore, how can I implement this function in less verbose way? Probable there is a way to shorten nested match constructions below?

use log::warn;

use diesel::prelude::*;
use diesel::result;

use crate::db::{get_connection, PgPool};
use crate::models::{NewUser, User};

pub fn get_or_create_user(pool: &PgPool, email: &str) -> User {
    use crate::schema::users;

    let new_user = NewUser { email };
    let mut conn = get_connection(pool);

    let result = diesel::insert_into(users::table)
        .values(&new_user)
        .get_result(&mut conn);

    match result {
        Ok(user) => return user,
        Err(err) => match err {
            result::Error::DatabaseError(err_kind, info) => match err_kind {
                result::DatabaseErrorKind::UniqueViolation => {
                    warn!(
                        "{:?} is already exists. Info: {:?}. Skipping.",
                        new_user, info
                    );
                    // another query to DB to get existing user by email
                    let user = user_by_email(pool, new_user.email);
                    return user;
                }
                _ => {
                    panic!("Database error: {:?}", info);
                }
            },
            _ => {
                // TODO: decide how to deal with unexpected errors
                return User {
                    id: 0,
                    email: "".into(),
                };
            }
        },
    }
}

pub fn user_by_email(pool: &PgPool, user_email: &str) -> User {
    use crate::schema::users::dsl::*;

    let mut conn = get_connection(pool);

    let user = crate::schema::users::dsl::users
        .filter(email.eq(user_email))
        .first(&mut conn)
        .unwrap();
    return user;
}
```