use crate::{load_named_records, Dict};
use anyhow::Result;
use serde::de::DeserializeOwned;
use std::future::Future;
pub struct DatabaseSeeder {
pub filenames: Vec<String>,
pub base_dir: String,
name_resolver: Dict<String>,
}
impl Default for DatabaseSeeder {
fn default() -> Self {
Self::new()
}
}
impl DatabaseSeeder {
pub fn new() -> Self {
Self {
filenames: Vec::new(),
base_dir: String::new(),
name_resolver: Dict::<String>::new(),
}
}
pub fn set_dir(&mut self, base_dir: &str) {
self.base_dir = base_dir.to_string();
}
pub fn populate<F, T, U>(&mut self, filename: &str, mut loader: F) -> Result<Vec<U>>
where
F: FnMut(T) -> Result<U>,
T: DeserializeOwned,
U: ToString,
{
let named_records = load_named_records::<T>(filename, &self.base_dir, &self.name_resolver)?;
let mut ids = Vec::new();
for (name, record) in named_records {
let id = loader(record)?;
self.name_resolver.insert(name.clone(), id.to_string());
ids.push(id);
}
Ok(ids)
}
pub async fn populate_async<Fut, F, T, U>(
&mut self,
filename: &str,
mut loader: F,
) -> Result<Vec<U>>
where
Fut: Future<Output = Result<U>>,
F: FnMut(T) -> Fut,
T: DeserializeOwned,
U: ToString,
{
let named_records = load_named_records::<T>(filename, &self.base_dir, &self.name_resolver)?;
self.filenames.push(filename.to_string());
let mut ids = Vec::new();
for (name, record) in named_records {
let id = loader(record).await?;
self.name_resolver.insert(name.clone(), id.to_string());
ids.push(id);
}
Ok(ids)
}
}