review: avoid using class string relying on T and EAV trait

This commit is contained in:
2025-10-02 07:17:46 +02:00
parent 733ffc36aa
commit cad5539a44
5 changed files with 42 additions and 29 deletions

View File

@@ -64,17 +64,16 @@ impl O {
/// An `Option<T>` containing the converted entity if found, otherwise `None`. /// An `Option<T>` containing the converted entity if found, otherwise `None`.
pub fn get<T>(&self, id: &str) -> Option<T> pub fn get<T>(&self, id: &str) -> Option<T>
where where
T: From<Entity>, T: EAV,
{ {
let entity = self.items.get(id); let entity = self.items.get(id);
entity.map(|e| T::from(e.clone())) entity.map(|e| T::from(e.clone()))
} }
/// Retrieves the first entity that matches a given class, attribute, and value. /// Retrieves the first entity that matches a given attribute and value.
/// ///
/// # Arguments /// # Arguments
/// ///
/// * `class` - The class of the entity to search for.
/// * `attribute` - The attribute of the entity to match. /// * `attribute` - The attribute of the entity to match.
/// * `value` - The value of the attribute to match. /// * `value` - The value of the attribute to match.
/// ///
@@ -83,17 +82,16 @@ impl O {
/// An `Option<T>` containing the converted entity if found, otherwise `None`. /// An `Option<T>` containing the converted entity if found, otherwise `None`.
pub fn get_by_class_and_attribute<T>( pub fn get_by_class_and_attribute<T>(
&self, &self,
class: &str,
attribute: &str, attribute: &str,
value: impl Into<Value> + Clone, value: impl Into<Value> + Clone,
) -> Option<T> ) -> Option<T>
where where
T: From<Entity>, T: EAV,
{ {
let mut items = self let mut items = self
.items .items
.values() .values()
.filter(|item| item.class == class) .filter(|item| item.class == T::class())
.filter(|item| item.value_of(attribute) == Some(&value.clone().into())) .filter(|item| item.value_of(attribute) == Some(&value.clone().into()))
.take(1) .take(1)
.map(|item| T::from(item.clone())); .map(|item| T::from(item.clone()));
@@ -102,28 +100,23 @@ impl O {
/// Returns an iterator over entities of a specific class. /// Returns an iterator over entities of a specific class.
/// ///
/// # Arguments
///
/// * `class` - The class of the entities to list.
///
/// # Returns /// # Returns
/// ///
/// An iterator that yields items of type `T`. /// An iterator that yields items of type `T`.
pub fn list_by_class<T>(&self, class: &str) -> impl Iterator<Item = T> pub fn list_by_class<T>(&self) -> impl Iterator<Item = T>
where where
T: From<Entity>, T: EAV,
{ {
self.items self.items
.values() .values()
.filter(move |item| item.class == class) .filter(move |item| item.class == T::class())
.map(|item| T::from(item.clone())) .map(|item| T::from(item.clone()))
} }
/// Returns an iterator over entities that match a given class, attribute, and value. /// Returns an iterator over entities that match a given attribute and value.
/// ///
/// # Arguments /// # Arguments
/// ///
/// * `class` - The class of the entities to search for.
/// * `attribute` - The attribute of the entities to match. /// * `attribute` - The attribute of the entities to match.
/// * `value` - The value of the attribute to match. /// * `value` - The value of the attribute to match.
/// ///
@@ -132,17 +125,16 @@ impl O {
/// An iterator that yields items of type `T`. /// An iterator that yields items of type `T`.
pub fn list_by_class_and_attribute<T>( pub fn list_by_class_and_attribute<T>(
&self, &self,
class: &str,
attribute: &str, attribute: &str,
value: impl Into<Value> + Clone, value: impl Into<Value> + Clone,
) -> impl Iterator<Item = T> ) -> impl Iterator<Item = T>
where where
T: From<Entity>, T: EAV,
{ {
let value: Value = value.into(); let value: Value = value.into();
self.items self.items
.values() .values()
.filter(move |item| item.class == class) .filter(move |item| item.class == T::class())
.filter(move |item| item.value_of(attribute) == Some(&value)) .filter(move |item| item.value_of(attribute) == Some(&value))
.map(|item| T::from(item.clone())) .map(|item| T::from(item.clone()))
} }
@@ -170,11 +162,11 @@ impl O {
} }
/// Loads all entities of a specific class from the database into the catalog. /// Loads all entities of a specific class from the database into the catalog.
/// pub fn load_by_class<T>(&mut self)
/// # Arguments where
/// T: EAV,
/// * `class` - The class of the entities to load. {
pub fn load_by_class(&mut self, class: &str) { let class = T::class();
let path = path::Path::new(&self.path); let path = path::Path::new(&self.path);
let entities = sqlite::load::by_class(path, class); let entities = sqlite::load::by_class(path, class);
for entity in entities { for entity in entities {

View File

@@ -9,7 +9,11 @@ pub struct O {
pub attributes: std::collections::HashMap<String, Attribute>, pub attributes: std::collections::HashMap<String, Attribute>,
} }
impl EAV for Entity {} impl EAV for Entity {
fn class() -> &'static str {
"entity"
}
}
impl O { impl O {
pub fn new(class: &str) -> Self { pub fn new(class: &str) -> Self {

View File

@@ -5,6 +5,7 @@ pub trait T where
Self: From<Entity>, Self: From<Entity>,
Self: Into<Entity>, Self: Into<Entity>,
{ {
fn class() -> &'static str;
} }
// #[cfg(test)] // #[cfg(test)]

View File

@@ -7,7 +7,11 @@ mod tests {
pub name: String, pub name: String,
pub price: u64, pub price: u64,
} }
impl EAV for Product {} impl EAV for Product {
fn class() -> &'static str {
"product"
}
}
impl From<Product> for Entity { impl From<Product> for Entity {
fn from(value: Product) -> Entity { fn from(value: Product) -> Entity {
Entity::default() Entity::default()
@@ -208,7 +212,7 @@ mod tests {
catalog.persist(); catalog.persist();
// new empty catalog // new empty catalog
let mut catalog = Catalog::new(path.to_str().unwrap()); let mut catalog = Catalog::new(path.to_str().unwrap());
catalog.load_by_class("product"); catalog.load_by_class::<Product>();
assert_eq!(catalog.items.len(), 2); assert_eq!(catalog.items.len(), 2);
let loaded_value_01: Product = catalog.get(&expected_value_01.id).unwrap(); let loaded_value_01: Product = catalog.get(&expected_value_01.id).unwrap();
assert_eq!(loaded_value_01, expected_value_01); assert_eq!(loaded_value_01, expected_value_01);

View File

@@ -11,7 +11,11 @@ mod tests {
pub operation_id: String, pub operation_id: String,
pub category_id: String, pub category_id: String,
} }
impl EAV for OperationToCategory {} impl EAV for OperationToCategory {
fn class() -> &'static str {
"operation_to_category"
}
}
impl From<OperationToCategory> for Entity { impl From<OperationToCategory> for Entity {
fn from(value: OperationToCategory) -> Entity { fn from(value: OperationToCategory) -> Entity {
Entity::default() Entity::default()
@@ -37,7 +41,11 @@ mod tests {
pub id: String, pub id: String,
pub label: String, pub label: String,
} }
impl EAV for Category {} impl EAV for Category {
fn class() -> &'static str {
"category"
}
}
impl From<Category> for Entity { impl From<Category> for Entity {
fn from(value: Category) -> Entity { fn from(value: Category) -> Entity {
Entity::default() Entity::default()
@@ -63,7 +71,11 @@ mod tests {
pub amount: i64, pub amount: i64,
pub description: String, pub description: String,
} }
impl EAV for Operation {} impl EAV for Operation {
fn class() -> &'static str {
"operation"
}
}
impl From<Operation> for Entity { impl From<Operation> for Entity {
fn from(value: Operation) -> Entity { fn from(value: Operation) -> Entity {
Entity::default() Entity::default()