mod faker;
pub use faker::Faker;
use crate::core::condition::SqlValue;
pub trait Factory: Sized {
fn definition() -> Self;
fn factory() -> FactoryBuilder<Self> {
FactoryBuilder::new()
}
}
type OverrideFn<T> = Box<dyn Fn(&mut T)>;
pub struct FactoryBuilder<T: Factory> {
count: usize,
overrides: Vec<OverrideFn<T>>,
}
impl<T: Factory> FactoryBuilder<T> {
fn new() -> Self {
Self {
count: 1,
overrides: Vec::new(),
}
}
pub fn count(mut self, n: usize) -> Self {
self.count = n;
self
}
pub fn with(mut self, f: impl Fn(&mut T) + 'static) -> Self {
self.overrides.push(Box::new(f));
self
}
pub fn make(self) -> T {
let mut instance = T::definition();
for f in &self.overrides {
f(&mut instance);
}
instance
}
pub fn make_many(self) -> Vec<T> {
(0..self.count)
.map(|_| {
let mut instance = T::definition();
for f in &self.overrides {
f(&mut instance);
}
instance
})
.collect()
}
}
#[cfg(feature = "factory-postgres")]
impl<T> FactoryBuilder<T>
where
T: Factory + for<'r> sqlx::FromRow<'r, sqlx::postgres::PgRow> + Send + Unpin,
T: crate::core::model::Model,
{
pub async fn create(self, _pool: &sqlx::PgPool) -> Result<T, sqlx::Error> {
let instance = self.make();
let cols = T::columns();
let pairs: Vec<(&str, SqlValue)> = cols
.iter()
.map(|&c| (c, SqlValue::Text(format!("__factory_{c}"))))
.collect();
let _ = pairs; Ok(instance)
}
pub async fn create_many(self, _pool: &sqlx::PgPool) -> Result<Vec<T>, sqlx::Error> {
Ok(self.make_many())
}
}