add derive + docs
This commit is contained in:
parent
5da65fb603
commit
ca2b0036f0
11 changed files with 400 additions and 43 deletions
|
@ -1,4 +1,9 @@
|
|||
pub mod model;
|
||||
pub use model::historic::Historic;
|
||||
pub use model::reference::*;
|
||||
pub use model::valid::Validate;
|
||||
pub use model::Model;
|
||||
pub use mongod_derive as derive;
|
||||
|
||||
/// Get a `MongoDB` Client from the environment
|
||||
#[macro_export]
|
||||
|
|
109
src/model/mod.rs
109
src/model/mod.rs
|
@ -23,52 +23,83 @@ pub enum UpdateError {
|
|||
pub trait Model:
|
||||
Sized + Referencable + Validate + serde::Serialize + for<'a> serde::Deserialize<'a>
|
||||
{
|
||||
/// Insert the model into the database
|
||||
async fn insert(&self) {
|
||||
let db = get_mongo!();
|
||||
let collection = col!(db, Self::collection_name());
|
||||
collection
|
||||
.insert_one(mongodb::bson::to_document(self).unwrap(), None)
|
||||
.await
|
||||
.unwrap();
|
||||
/// Insert the `Model` into the database
|
||||
fn insert(&self) -> impl std::future::Future<Output = ()> + Send
|
||||
where
|
||||
Self: Sync,
|
||||
{
|
||||
async {
|
||||
let db = get_mongo!();
|
||||
let collection = col!(db, Self::collection_name());
|
||||
collection
|
||||
.insert_one(mongodb::bson::to_document(self).unwrap(), None)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a model by id from the database
|
||||
async fn get(id: &str) -> Option<Self> {
|
||||
let db = get_mongo!();
|
||||
let collection = col!(db, Self::collection_name());
|
||||
let doc = collection.find_one(id_of!(id), None).await.ok()??;
|
||||
mongodb::bson::from_document(doc).ok()
|
||||
/// Remove a `Model` from the database.
|
||||
fn remove(id: &str) -> impl std::future::Future<Output = ()> + Send {
|
||||
async move {
|
||||
let db = get_mongo!();
|
||||
let collection = col!(db, Self::collection_name());
|
||||
collection.delete_one(id_of!(id), None).await.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
/// Update values of model into database
|
||||
async fn update(&mut self, data: &serde_json::Value) -> Result<(), UpdateError> {
|
||||
// get db collection
|
||||
let db = get_mongo!();
|
||||
let collection = col!(db, Self::collection_name());
|
||||
let mut update = mongodb::bson::Document::new();
|
||||
/// Remove a `Model` from the database.
|
||||
///
|
||||
/// This is a convenience function to let you call `remove()` on a `Model` you have at hand.
|
||||
fn delete(&self) -> impl std::future::Future<Output = ()> + Send
|
||||
where
|
||||
Self: Sync,
|
||||
{
|
||||
async { Self::remove(self.id()).await }
|
||||
}
|
||||
|
||||
if let Some(obj) = data.as_object() {
|
||||
// run model specific update
|
||||
self.update_values(obj, &mut update).await;
|
||||
/// Get a `Model` by id from the database
|
||||
#[must_use]
|
||||
fn get(id: &str) -> impl std::future::Future<Output = Option<Self>> {
|
||||
async move {
|
||||
let db = get_mongo!();
|
||||
let collection = col!(db, Self::collection_name());
|
||||
let doc = collection.find_one(id_of!(id), None).await.ok()??;
|
||||
mongodb::bson::from_document(doc).ok()
|
||||
}
|
||||
}
|
||||
|
||||
// validate and update
|
||||
if self.validate().await {
|
||||
collection
|
||||
.update_one(
|
||||
id_of!(self.id()),
|
||||
mongodb::bson::doc! {"$set": update },
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.map_err(|_| UpdateError::Database)?;
|
||||
return Ok(());
|
||||
} else {
|
||||
/// Update values of `Model` into database
|
||||
fn update(
|
||||
&mut self,
|
||||
data: &serde_json::Value,
|
||||
) -> impl std::future::Future<Output = Result<(), UpdateError>> {
|
||||
async {
|
||||
// get db collection
|
||||
let db = get_mongo!();
|
||||
let collection = col!(db, Self::collection_name());
|
||||
let mut update = mongodb::bson::Document::new();
|
||||
|
||||
if let Some(obj) = data.as_object() {
|
||||
// run model specific update
|
||||
self.update_values(obj, &mut update).await;
|
||||
|
||||
// validate and update
|
||||
if self.validate().await {
|
||||
collection
|
||||
.update_one(
|
||||
id_of!(self.id()),
|
||||
mongodb::bson::doc! {"$set": update },
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.map_err(|_| UpdateError::Database)?;
|
||||
return Ok(());
|
||||
}
|
||||
return Err(UpdateError::Validation);
|
||||
}
|
||||
}
|
||||
|
||||
Err(UpdateError::NoObject)
|
||||
Err(UpdateError::NoObject)
|
||||
}
|
||||
}
|
||||
|
||||
/// Update the `Model` based on the provided JSON Object.
|
||||
|
@ -77,9 +108,9 @@ pub trait Model:
|
|||
/// For every updated value in the JSON Object the `Model`s fields should be updated and the value should be put in the `update` `Document`
|
||||
///
|
||||
/// To avoid making mistakes in the Update logic use the macros from `update.rs`
|
||||
async fn update_values(
|
||||
fn update_values(
|
||||
&mut self,
|
||||
obj: &Map<String, Value>,
|
||||
update: &mut mongodb::bson::Document,
|
||||
);
|
||||
) -> impl std::future::Future<Output = ()> + Send;
|
||||
}
|
||||
|
|
|
@ -9,8 +9,8 @@ use super::valid::Validate;
|
|||
pub struct Reference(String);
|
||||
|
||||
impl Reference {
|
||||
/// Create a new reference
|
||||
pub async fn new(reference: &str) -> Option<Self> {
|
||||
/// Create a new reference from String
|
||||
pub async fn new_raw(reference: &str) -> Option<Self> {
|
||||
let r = Self(reference.to_string());
|
||||
if r.validate().await {
|
||||
Some(r)
|
||||
|
@ -19,7 +19,13 @@ impl Reference {
|
|||
}
|
||||
}
|
||||
|
||||
/// Create a new reference
|
||||
pub async fn new(model: &str, id: &str) -> Option<Self> {
|
||||
Self::new_raw(&format!("{model}::{id}")).await
|
||||
}
|
||||
|
||||
/// Checks if a reference is part of a model collection.
|
||||
#[must_use]
|
||||
pub fn is_of_collection(&self, col: &str) -> bool {
|
||||
self.0.starts_with(col)
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ macro_rules! update_historic_ref_option {
|
|||
($entity:ident, $json:ident, $key:literal, $field:ident, $update:ident) => {
|
||||
if let Some(val) = $json.get($key) {
|
||||
if let Some(val_str) = val.as_str() {
|
||||
let value = Historic::new(Reference::new(val_str).await.unwrap());
|
||||
let value = Historic::new(Reference::new_raw(val_str).await.unwrap());
|
||||
let field = $entity.$field.clone().unwrap_or_else(|| value);
|
||||
$entity.$field = Some(field);
|
||||
$update.insert($key, mongodb::bson::to_bson(&$entity.$field).unwrap());
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/// This trait allows a `Model` to be validated.
|
||||
pub trait Validate {
|
||||
/// Validate the `Model`
|
||||
async fn validate(&self) -> bool;
|
||||
fn validate(&self) -> impl std::future::Future<Output = bool> + Send;
|
||||
}
|
||||
|
||||
/// Validate a value and return `false` if validation fails.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue