recipes/api/src/repo/recipe.rs

162 lines
4.9 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use crate::domain::{Context, Ingredient, Lang, Measure, Recipe, RecipeIngredient};
#[cfg(test)]
use crate::repo::ingredient::InMemoryIngredientRepo;
use crate::repo::ingredient::{IngredientRepo, StaticIngredientRepo};
pub trait RecipeRepo {
fn get_recipes(&self, ctx: &Context) -> Vec<Recipe>;
}
pub struct StaticRecipeRepo;
impl RecipeRepo for StaticRecipeRepo {
fn get_recipes(&self, ctx: &Context) -> Vec<Recipe> {
let ings_repo = StaticIngredientRepo;
let ings = ings_repo.get_ingredients(ctx, Default::default());
db::data::RECIPES
.iter()
.filter_map(|rec| Recipe::try_from((rec, ctx.lang, ings.clone())).ok())
.collect()
}
}
#[cfg(test)]
pub struct InMemoryRecipeRepo {
pub recipes: Vec<db::Recipe>,
}
#[cfg(test)]
impl RecipeRepo for InMemoryRecipeRepo {
fn get_recipes(&self, ctx: &Context) -> Vec<Recipe> {
let ings_repo = InMemoryIngredientRepo::new();
let ings = ings_repo.get_ingredients(ctx, Default::default());
self.recipes
.iter()
.filter_map(|rec| Recipe::try_from((rec, ctx.lang, ings.clone())).ok())
.collect()
}
}
#[cfg(test)]
impl InMemoryRecipeRepo {
pub fn new() -> Self {
Self {
recipes: vec![db::Recipe {
key: "fruit_salad",
steps: 0,
ingredients: vec![
db::RecipeIngredient {
key: "banana",
measure: db::Measure::Gram(150),
},
db::RecipeIngredient {
key: "apple",
measure: db::Measure::Gram(150),
},
db::RecipeIngredient {
key: "orange",
measure: db::Measure::Gram(150),
},
],
translates: db::RecipeTranslates {
rus: db::RecipeTranslate {
name: "Фруктовый салат",
instructions: vec![
"Нарезать бананы кружочками",
"Нарезать яблоки и апельсины кубиками",
"Все ингредиенты перемешать",
],
},
eng: None,
},
}],
}
}
pub fn with_no_ingredients_found(mut self) -> Self {
self.recipes.push(db::Recipe {
key: "no_ingredients_found",
steps: 0,
ingredients: vec![
db::RecipeIngredient {
key: "salt",
measure: db::Measure::Gram(5),
},
db::RecipeIngredient {
key: "sugar",
measure: db::Measure::Gram(4),
},
db::RecipeIngredient {
key: "wheat_flour",
measure: db::Measure::Gram(500),
},
],
translates: db::RecipeTranslates {
rus: db::RecipeTranslate {
name: "Не найдены ингредиенты",
instructions: vec![],
},
eng: None,
},
});
self
}
}
impl TryFrom<(&db::Recipe, Lang, Vec<Ingredient>)> for Recipe {
type Error = ();
fn try_from(
(db, lang, ingredients): (&db::Recipe, Lang, Vec<Ingredient>),
) -> Result<Self, Self::Error> {
let tr = &db.translates;
let ctr = match lang {
Lang::Rus => &tr.rus,
Lang::Eng => tr.eng.as_ref().unwrap_or(&tr.rus),
};
let ingredients = db
.ingredients
.iter()
.map(|sing| {
ingredients
.iter()
.find(|ing| sing.key == ing.key)
.map(|ing| RecipeIngredient {
ingredient: ing.clone(),
measure: sing.measure.into(),
})
.ok_or(())
})
.collect::<Result<Vec<_>, _>>()?;
let instructions = ctr.instructions.iter().copied().map(String::from).collect();
Ok(Self {
key: db.key.to_string(),
lang: if ctr.name == tr.rus.name {
Lang::Rus
} else {
lang
},
name: ctr.name.to_string(),
instructions,
ingredients,
})
}
}
impl From<db::Measure> for Measure {
fn from(db: db::Measure) -> Self {
match db {
db::Measure::Gram(val) => Measure::Gram(val),
db::Measure::KiloGram(val) => Measure::KiloGram(val),
db::Measure::MilliLiter(val) => Measure::MilliLiter(val),
db::Measure::Liter(val) => Measure::Liter(val),
}
}
}