use sqlx::Pool;
use crate::error::{ModelError, ModelResult};
use crate::model::core_trait::Model;
use crate::model::crud_operations::CrudOperations;
#[allow(async_fn_in_trait)]
pub trait ModelExtensions: Model + CrudOperations {
async fn refresh(&mut self, pool: &Pool<sqlx::Postgres>) -> ModelResult<()>
where
Self: Sized,
{
if let Some(pk) = self.primary_key() {
if let Some(refreshed) = Self::find(pool, pk).await? {
*self = refreshed;
Ok(())
} else {
Err(ModelError::NotFound(Self::table_name().to_string()))
}
} else {
Err(ModelError::MissingPrimaryKey)
}
}
async fn exists(&self, pool: &Pool<sqlx::Postgres>) -> ModelResult<bool>
where
Self: Sized,
{
if let Some(pk) = self.primary_key() {
let exists = Self::find(pool, pk).await?.is_some();
Ok(exists)
} else {
Ok(false)
}
}
async fn save(&mut self, pool: &Pool<sqlx::Postgres>) -> ModelResult<()>
where
Self: Sized + Clone,
{
if self.primary_key().is_some() && self.exists(pool).await? {
self.update(pool).await
} else {
let new_model = Self::create(pool, self.clone()).await?;
*self = new_model;
Ok(())
}
}
fn duplicate(&self) -> Self
where
Self: Sized + Clone,
{
let mut cloned = self.clone();
cloned.set_primary_key(Self::PrimaryKey::default());
if Self::uses_timestamps() {
cloned.set_created_at(chrono::Utc::now());
cloned.set_updated_at(chrono::Utc::now());
}
if Self::uses_soft_deletes() {
cloned.set_deleted_at(None);
}
cloned
}
fn supports_transactions() -> bool
where
Self: Sized,
{
true }
fn is_dirty(&self) -> bool {
true
}
fn mark_clean(&mut self) {}
fn dirty_fields(&self) -> Vec<&str> {
vec![]
}
}
impl<T: Model + CrudOperations> ModelExtensions for T {}