From d8bebcc8f51d65219a7fa08721808e60dc92ac9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20=C5=BBo=C5=82nierowicz?= Date: Wed, 26 Jun 2024 17:04:29 +0200 Subject: [PATCH] ZED-22 replace hashmap with btreemap --- backend/src/domain/commands/recipes/create.rs | 14 +++---- backend/src/domain/entities/recipe/mod.rs | 40 ++++++++++++++----- .../repositories/ingredients/in_memory/mod.rs | 10 ++--- .../repositories/recipe/in_memory/tests.rs | 4 +- .../repositories/recipe/postgres/tests.rs | 4 +- backend/src/test_utils.rs | 6 +-- 6 files changed, 50 insertions(+), 28 deletions(-) diff --git a/backend/src/domain/commands/recipes/create.rs b/backend/src/domain/commands/recipes/create.rs index f9018c7..ed069e3 100644 --- a/backend/src/domain/commands/recipes/create.rs +++ b/backend/src/domain/commands/recipes/create.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::collections::BTreeMap; use rayon::iter::{IndexedParallelIterator, IntoParallelIterator, ParallelIterator}; use serde::{Deserialize, Serialize}; @@ -49,7 +49,7 @@ pub struct CreateRecipe<'a> { pub name: &'a str, pub description: &'a str, pub steps: Vec, - pub time: HashMap, + pub time: BTreeMap, pub ingredients: Vec, pub servings: ServingsType, } @@ -138,7 +138,7 @@ mod tests { &CreateRecipe { name: "Recipe test", description: "This is a test for the recipe", - time: HashMap::from([( + time: BTreeMap::from([( "Prep time".to_string(), std::time::Duration::from_secs(60), )]), @@ -159,7 +159,7 @@ mod tests { #[tokio::test] async fn create_recipe_with_proper_ingredients() { - let ingredients: HashMap = HashMap::from([( + let ingredients: BTreeMap = BTreeMap::from([( Uuid::nil(), IngredientModel { id: Uuid::nil(), @@ -188,7 +188,7 @@ mod tests { &CreateRecipe { name: "Recipe test", description: "This is a test for the recipe", - time: HashMap::from([( + time: BTreeMap::from([( "Prep time".to_string(), std::time::Duration::from_secs(60), )]), @@ -241,7 +241,7 @@ mod tests { &CreateRecipe { name: "Recipe test", description: "This is a test for the recipe", - time: HashMap::from([( + time: BTreeMap::from([( "Prep time".to_string(), std::time::Duration::from_secs(60), )]), @@ -292,7 +292,7 @@ mod tests { &CreateRecipe { name: "Recipe test", description: "This is a test for the recipe", - time: HashMap::from([( + time: BTreeMap::from([( "Prep time".to_string(), std::time::Duration::from_secs(60), )]), diff --git a/backend/src/domain/entities/recipe/mod.rs b/backend/src/domain/entities/recipe/mod.rs index c47c00d..ee38f76 100644 --- a/backend/src/domain/entities/recipe/mod.rs +++ b/backend/src/domain/entities/recipe/mod.rs @@ -1,5 +1,5 @@ pub mod errors; -use std::collections::HashMap; +use std::collections::BTreeMap; use common::{IngredientUnitDTO, IngredientWithAmountDTO, RecipeDTO, ServingsTypeDTO}; use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; @@ -18,11 +18,31 @@ pub struct Recipe { pub description: String, pub steps: RecipeSteps, pub ingredients: RecipeIngredients, - pub time: HashMap, + pub time: BTreeMap, pub servings: ServingsType, } +#[derive(Debug, Clone)] +pub struct RecipeIngredients(Vec); -#[derive(PartialEq, Debug, Clone)] +impl AsRef<[IngredientWithAmount]> for RecipeIngredients { + fn as_ref(&self) -> &[IngredientWithAmount] { + &self.0 + } +} + +impl PartialEq for RecipeIngredients { + fn eq(&self, other: &Self) -> bool { + let mut a = self.0.clone(); + let mut b = other.0.clone(); + a.sort_by_key(|f| f.ingredient.id); + b.sort_by_key(|f| f.ingredient.id); + + a.eq(&b) + } +} + + +#[derive(Debug, Clone)] pub struct RecipeSteps(Vec); impl AsRef<[String]> for RecipeSteps { @@ -31,12 +51,14 @@ impl AsRef<[String]> for RecipeSteps { } } -#[derive(PartialEq, Debug, Clone)] -pub struct RecipeIngredients(Vec); +impl PartialEq for RecipeSteps { + fn eq(&self, other: &Self) -> bool { + let mut a = self.0.clone(); + let mut b = other.0.clone(); + a.sort(); + b.sort(); -impl AsRef<[IngredientWithAmount]> for RecipeIngredients { - fn as_ref(&self) -> &[IngredientWithAmount] { - &self.0 + a.eq(&b) } } @@ -225,7 +247,7 @@ pub struct RecipeChangeset { pub name: Option, pub description: Option, pub steps: Option, - pub time: Option>, + pub time: Option>, pub servings: Option, } diff --git a/backend/src/domain/repositories/ingredients/in_memory/mod.rs b/backend/src/domain/repositories/ingredients/in_memory/mod.rs index 2ee9c63..0c23978 100644 --- a/backend/src/domain/repositories/ingredients/in_memory/mod.rs +++ b/backend/src/domain/repositories/ingredients/in_memory/mod.rs @@ -1,5 +1,5 @@ use std::{ - collections::{HashMap, HashSet}, + collections::{BTreeMap, HashSet}, sync::Mutex, }; @@ -18,7 +18,7 @@ use super::{ IngredientRepository, }; -pub struct InMemoryIngredientRepository(pub Mutex>); +pub struct InMemoryIngredientRepository(pub Mutex>); #[async_trait] impl IngredientRepository for InMemoryIngredientRepository { @@ -145,7 +145,7 @@ impl IngredientRepository for InMemoryIngredientRepository { impl InMemoryIngredientRepository { pub fn new() -> Self { - HashMap::new().into() + BTreeMap::new().into() } } @@ -155,8 +155,8 @@ impl Default for InMemoryIngredientRepository { } } -impl From> for InMemoryIngredientRepository { - fn from(value: HashMap) -> Self { +impl From> for InMemoryIngredientRepository { + fn from(value: BTreeMap) -> Self { Self(value.into()) } } diff --git a/backend/src/domain/repositories/recipe/in_memory/tests.rs b/backend/src/domain/repositories/recipe/in_memory/tests.rs index 95bef58..1ec78e6 100644 --- a/backend/src/domain/repositories/recipe/in_memory/tests.rs +++ b/backend/src/domain/repositories/recipe/in_memory/tests.rs @@ -1,4 +1,4 @@ -use std::time::Duration; +use std::{collections::BTreeMap, time::Duration}; use crate::{ domain::entities::recipe::ServingsType, @@ -90,7 +90,7 @@ async fn updating_a_recipe_succeeds() { steps: vec!["WE UPDATED ANOTHER THING".to_string()] .try_into() .unwrap(), - time: HashMap::from([("Prep time".to_string(), Duration::from_secs(60))]), + time: BTreeMap::from([("Prep time".to_string(), Duration::from_secs(60))]), servings: ServingsType::Exact(4), ..recipe } diff --git a/backend/src/domain/repositories/recipe/postgres/tests.rs b/backend/src/domain/repositories/recipe/postgres/tests.rs index 7b03b44..87c396c 100644 --- a/backend/src/domain/repositories/recipe/postgres/tests.rs +++ b/backend/src/domain/repositories/recipe/postgres/tests.rs @@ -1,4 +1,4 @@ -use std::{collections::HashMap, time::Duration}; +use std::{collections::BTreeMap, time::Duration}; use crate::{ domain::{ @@ -117,7 +117,7 @@ async fn updating_a_recipe_succeeds(pool: PgPool) { steps: vec!["WE UPDATED ANOTHER THING".to_string()] .try_into() .unwrap(), - time: HashMap::from([("Prep time".to_string(), Duration::from_secs(60))]), + time: BTreeMap::from([("Prep time".to_string(), Duration::from_secs(60))]), servings: ServingsType::Exact(4), ..recipe } diff --git a/backend/src/test_utils.rs b/backend/src/test_utils.rs index 37e7796..5827687 100644 --- a/backend/src/test_utils.rs +++ b/backend/src/test_utils.rs @@ -1,4 +1,4 @@ -use std::{collections::HashMap, time::Duration}; +use std::{collections::BTreeMap, time::Duration}; use crate::domain::entities::recipe::{ IngredientUnit, IngredientWithAmount, RecipeChangeset, ServingsType, @@ -14,7 +14,7 @@ pub fn recipe_fixture() -> Recipe { id: uuid::Uuid::nil(), name: "Hoisin Tofu and Broccoli".to_string(), description: "If necessary, provide a very brief description of the dish in one or two sentences. For most dishes, this will be unnecessary. If there is a title image of this dish, it should be above this paragraph. You may also include prep/cook time and the number of servings as below:".to_string(), - time: HashMap::from([ + time: BTreeMap::from([ ("Prep time".to_string(), Duration::from_secs(15 * 60)), ("Cook time".to_string(), Duration::from_secs(10 * 60)) ]), @@ -85,7 +85,7 @@ pub fn recipe_changeset() -> RecipeChangeset { RecipeChangeset { name: Some("WE UPDATED THIS THING".to_string()), description: Some("WE UPDATED THAT THING".to_string()), - time: Some(HashMap::from([( + time: Some(BTreeMap::from([( "Prep time".to_string(), Duration::from_secs(60), )])),