#[cfg(feature = "sqlite")]
use ormer::{
AfterDelete, AfterInsert, AfterUpdate, BeforeDelete, BeforeInsert, BeforeUpdate, Database,
DbType, Model,
};
#[cfg(not(feature = "sqlite"))]
use ormer::{
AfterDelete, AfterInsert, AfterUpdate, BeforeDelete, BeforeInsert, BeforeUpdate, Model,
};
use std::sync::atomic::{AtomicUsize, Ordering};
static BEFORE_INSERT_COUNT: AtomicUsize = AtomicUsize::new(0);
static AFTER_INSERT_COUNT: AtomicUsize = AtomicUsize::new(0);
static BEFORE_UPDATE_COUNT: AtomicUsize = AtomicUsize::new(0);
static AFTER_UPDATE_COUNT: AtomicUsize = AtomicUsize::new(0);
static BEFORE_DELETE_COUNT: AtomicUsize = AtomicUsize::new(0);
static AFTER_DELETE_COUNT: AtomicUsize = AtomicUsize::new(0);
#[derive(Debug, Model)]
#[table = "hook_test_users"]
struct HookTestUser {
#[primary(auto)]
id: i32,
name: String,
email: String,
}
#[async_trait::async_trait]
impl BeforeInsert for HookTestUser {
async fn before_insert(&mut self) {
BEFORE_INSERT_COUNT.fetch_add(1, Ordering::SeqCst);
}
}
#[async_trait::async_trait]
impl AfterInsert for HookTestUser {
async fn after_insert(&self) {
AFTER_INSERT_COUNT.fetch_add(1, Ordering::SeqCst);
}
}
#[async_trait::async_trait]
impl BeforeUpdate for HookTestUser {
async fn before_update(&mut self) {
BEFORE_UPDATE_COUNT.fetch_add(1, Ordering::SeqCst);
}
}
#[async_trait::async_trait]
impl AfterUpdate for HookTestUser {
async fn after_update(&self) {
AFTER_UPDATE_COUNT.fetch_add(1, Ordering::SeqCst);
}
}
#[async_trait::async_trait]
impl BeforeDelete for HookTestUser {
async fn before_delete(&self) {
BEFORE_DELETE_COUNT.fetch_add(1, Ordering::SeqCst);
}
}
#[async_trait::async_trait]
impl AfterDelete for HookTestUser {
async fn after_delete(&self) {
AFTER_DELETE_COUNT.fetch_add(1, Ordering::SeqCst);
}
}
fn reset_counters() {
BEFORE_INSERT_COUNT.store(0, Ordering::SeqCst);
AFTER_INSERT_COUNT.store(0, Ordering::SeqCst);
BEFORE_UPDATE_COUNT.store(0, Ordering::SeqCst);
AFTER_UPDATE_COUNT.store(0, Ordering::SeqCst);
BEFORE_DELETE_COUNT.store(0, Ordering::SeqCst);
AFTER_DELETE_COUNT.store(0, Ordering::SeqCst);
}
#[tokio::test]
async fn test_hooks_trait_definition() {
reset_counters();
let mut user = HookTestUser {
id: 0,
name: "Test User".to_string(),
email: "test@example.com".to_string(),
};
user.before_insert().await;
assert_eq!(BEFORE_INSERT_COUNT.load(Ordering::SeqCst), 1);
user.after_insert().await;
assert_eq!(AFTER_INSERT_COUNT.load(Ordering::SeqCst), 1);
user.before_update().await;
assert_eq!(BEFORE_UPDATE_COUNT.load(Ordering::SeqCst), 1);
user.after_update().await;
assert_eq!(AFTER_UPDATE_COUNT.load(Ordering::SeqCst), 1);
user.before_delete().await;
assert_eq!(BEFORE_DELETE_COUNT.load(Ordering::SeqCst), 1);
user.after_delete().await;
assert_eq!(AFTER_DELETE_COUNT.load(Ordering::SeqCst), 1);
}
#[cfg(feature = "sqlite")]
#[tokio::test]
async fn test_hooks_with_database_insert() {
reset_counters();
#[cfg(feature = "sqlite")]
{
let db = Database::connect(DbType::Sqlite, ":memory:").await.unwrap();
db.create_table::<HookTestUser>().execute().await.unwrap();
let user = HookTestUser {
id: 0,
name: "Alice".to_string(),
email: "alice@example.com".to_string(),
};
db.insert(&user).execute().await.unwrap();
}
}
#[cfg(feature = "sqlite")]
#[tokio::test]
async fn test_hooks_with_database_batch_insert() {
reset_counters();
#[cfg(feature = "sqlite")]
{
let db = Database::connect(DbType::Sqlite, ":memory:").await.unwrap();
db.create_table::<HookTestUser>().execute().await.unwrap();
let users = vec![
HookTestUser {
id: 0,
name: "Bob".to_string(),
email: "bob@example.com".to_string(),
},
HookTestUser {
id: 0,
name: "Charlie".to_string(),
email: "charlie@example.com".to_string(),
},
];
db.insert(&users).execute().await.unwrap();
}
}