Hello
In my Actix-Web project I have a few structs
which represent the tables in my MySQL-database. But I am wondering if it's more clean to implement the CRUD-functions in the struct itself, or to make a separate function for it.
Option 1: Function to retrieve a Order
-object implemented in struct.
#[derive(Deserialize, Serialize, Clone)]
pub struct Order {
id: u64,
user: User,
restaurant: Restaurant,
address: Address,
transaction_fee: f64,
delivery_cost: f64,
payment_id: String,
paid: bool,
order_date: Option<chrono::DateTime<chrono::Utc>>,
}
impl Order {
pub async fn retrieve(order_id: u64, mysql: &web::Data<MySQL>) -> Option<Order> {
let result = sqlx::query("SELECT ID, order_date, user, restaurant, address, transaction_fee, delivery_cost, payment_id, paid FROM `order` WHERE ID=?")
.bind(order_id)
.fetch_one(&mysql.conn)
.await;
match result {
Err(e) => {
println!("Error [in get_order(), data.rs]: {}", e);
None
}
Ok(r) => Some(Order {
id: r.try_get("ID").unwrap(),
user: User::get(Selector::ById(r.try_get("user").unwrap()), mysql)
.await
.unwrap(),
restaurant: get_restaurant(r.try_get("restaurant").unwrap(), mysql)
.await
.unwrap(),
address: get_address(r.try_get("address").unwrap(), mysql)
.await
.unwrap(),
transaction_fee: r.try_get("transaction_fee").unwrap(),
delivery_cost: r.try_get("delivery_cost").unwrap(),
payment_id: r.try_get("payment_id").unwrap(),
paid: r.try_get("paid").unwrap(),
order_date: r.try_get("order_date").unwrap(),
}),
}
}
// Called like
let order = Order::retrieve(1, &mysql).await.unwrap();
Option 2: Function to retrieve a Order
-object in separate module/file.
// main.rs
#[derive(Deserialize, Serialize, Clone)]
pub struct Order {
id: u64,
user: User,
restaurant: Restaurant,
address: Address,
transaction_fee: f64,
delivery_cost: f64,
payment_id: String,
paid: bool,
order_date: Option<chrono::DateTime<chrono::Utc>>,
}
// data.rs
pub async fn get_order(order_id: u64, mysql: &web::Data<MySQL>) -> Option<Order> {
let result = sqlx::query("SELECT ID, order_date, user, restaurant, address, transaction_fee, delivery_cost, payment_id, paid FROM `order` WHERE ID=?")
.bind(order_id)
.fetch_one(&mysql.conn)
.await;
match result {
Err(e) => {
println!("Error [in get_order(), data.rs]: {}", e);
None
}
Ok(r) => Some(Order {
id: r.try_get("ID").unwrap(),
user: User::get(Selector::ById(r.try_get("user").unwrap()), mysql)
.await
.unwrap(),
restaurant: get_restaurant(r.try_get("restaurant").unwrap(), mysql)
.await
.unwrap(),
address: get_address(r.try_get("address").unwrap(), mysql)
.await
.unwrap(),
transaction_fee: r.try_get("transaction_fee").unwrap(),
delivery_cost: r.try_get("delivery_cost").unwrap(),
payment_id: r.try_get("payment_id").unwrap(),
paid: r.try_get("paid").unwrap(),
order_date: r.try_get("order_date").unwrap(),
}),
}
}
// Called like
let order = data::get_order(1, mysql).await.unwrap();
What is the cleanest option? And would it be different for each CRUD-method? E.g, have the create
implemented in struct so I could do
Order {...}.create(mysql).
But have the retrieve
implemented in a different file?
Thanks.