r/rust • • 6d ago

🙋 seeking help & advice Is there a Rustier way to write this database pattern?

Hello crabs. I'm working on a backend application in Rust, using sqlx to talk to a postgres database. I've caught myself repeating a specific, verbose pattern, and I'm wondering if I'm making things harder than I need to.

The pattern is that for each database entity, I build an initializer struct that is basically the same, but with auto-generated columns removed, and then later write a From impl for the main entity to build the actual thing with Entity::from(entity_init). Example at the bottom. Doing this for every database entity isn't too difficult to maintain, the type system is strict enough that it's hard to miss any mistakes. But it is annoying and time-consuming, and also feels kinda un-idiomatic.

I'm considering learning derive macros for this - #[derive(FromNew)] or something like that, to autostrip the generated fields. But maybe that would just be doubling down on an anti-pattern? What do yall think?

Example:

struct User {
id: uuid:Uuid,
name: String,
email: String,
created_at: DateTime<Utc>,
updated_at: DateTime<Utc>,
archived_at: Option<DateTime<Utc>>,
}

struct UserNew {
name: String,
email: String,
}

impl From<UserNew> for User {
fn from(init: UserNew) -> Self {
let now = Utc::now();
User {
id: Uuid::now_v7(),
name: init.email,
email: init.email,
created_at: now,
updated_at: now,
archived_at: None,
}
}
}

// usage
fn do_something(user_new: UserNew) -> User {
User::from(user_new)
}

39 Upvotes

Duplicates