127 lines
3.8 KiB
Rust
127 lines
3.8 KiB
Rust
use crate::domain::ingredient::fetch_list;
|
||
use crate::domain::{Context, Ingredient, Lang};
|
||
|
||
#[derive(Default)]
|
||
pub struct GetIngredientsOpts {
|
||
pub keys: Option<Vec<String>>,
|
||
}
|
||
|
||
impl From<fetch_list::RequestOpts> for GetIngredientsOpts {
|
||
fn from(app: fetch_list::RequestOpts) -> Self {
|
||
Self { keys: app.keys }
|
||
}
|
||
}
|
||
|
||
pub trait IngredientRepo {
|
||
fn get_ingredient_opt(&self, ctx: &Context, key: String) -> Option<Ingredient>;
|
||
|
||
fn get_ingredients(&self, ctx: &Context, opts: GetIngredientsOpts) -> Vec<Ingredient>;
|
||
}
|
||
|
||
pub struct StaticIngredientRepo;
|
||
|
||
impl IngredientRepo for StaticIngredientRepo {
|
||
fn get_ingredient_opt(&self, ctx: &Context, key: String) -> Option<Ingredient> {
|
||
db::data::INGREDIENTS
|
||
.iter()
|
||
.find(|ing| ing.key == &key)
|
||
.map(|ing| Ingredient::from((ing, ctx.lang)))
|
||
}
|
||
|
||
fn get_ingredients(&self, ctx: &Context, opts: GetIngredientsOpts) -> Vec<Ingredient> {
|
||
let langs = [ctx.lang].repeat(db::data::INGREDIENTS.len());
|
||
db::data::INGREDIENTS
|
||
.iter()
|
||
.zip(langs)
|
||
.map(Ingredient::from)
|
||
.filter(|ing| opts.keys.is_none() || opts.keys.as_ref().unwrap().contains(&ing.key))
|
||
.collect::<Vec<_>>()
|
||
}
|
||
}
|
||
|
||
#[cfg(test)]
|
||
pub struct InMemoryIngredientRepo {
|
||
pub ingredients: Vec<db::Ingredient>,
|
||
}
|
||
|
||
#[cfg(test)]
|
||
impl IngredientRepo for InMemoryIngredientRepo {
|
||
fn get_ingredient_opt(&self, ctx: &Context, key: String) -> Option<Ingredient> {
|
||
self.ingredients
|
||
.iter()
|
||
.find(|ing| ing.key == &key)
|
||
.map(|ing| Ingredient::from((ing, ctx.lang)))
|
||
}
|
||
|
||
fn get_ingredients(&self, ctx: &Context, opts: GetIngredientsOpts) -> Vec<Ingredient> {
|
||
let langs = [ctx.lang].repeat(self.ingredients.len());
|
||
self.ingredients
|
||
.iter()
|
||
.zip(langs)
|
||
.map(Ingredient::from)
|
||
.filter(|ing| opts.keys.is_none() || opts.keys.as_ref().unwrap().contains(&ing.key))
|
||
.collect::<Vec<_>>()
|
||
}
|
||
}
|
||
|
||
#[cfg(test)]
|
||
impl InMemoryIngredientRepo {
|
||
pub fn new() -> Self {
|
||
Self {
|
||
ingredients: vec![
|
||
db::Ingredient {
|
||
key: "banana",
|
||
translates: db::IngredientTranslate {
|
||
rus: "Банан",
|
||
eng: Some("Banana"),
|
||
},
|
||
},
|
||
db::Ingredient {
|
||
key: "apple",
|
||
translates: db::IngredientTranslate {
|
||
rus: "Яблоко",
|
||
eng: Some("Apple"),
|
||
},
|
||
},
|
||
db::Ingredient {
|
||
key: "orange",
|
||
translates: db::IngredientTranslate {
|
||
rus: "Апельсин",
|
||
eng: None,
|
||
},
|
||
},
|
||
db::Ingredient {
|
||
key: "salt",
|
||
translates: db::IngredientTranslate {
|
||
rus: "Соль",
|
||
eng: Some("Salt"),
|
||
},
|
||
},
|
||
db::Ingredient {
|
||
key: "sugar",
|
||
translates: db::IngredientTranslate {
|
||
rus: "Сахар",
|
||
eng: None,
|
||
},
|
||
},
|
||
],
|
||
}
|
||
}
|
||
}
|
||
|
||
impl From<(&db::Ingredient, Lang)> for Ingredient {
|
||
fn from((db, lang): (&db::Ingredient, Lang)) -> Self {
|
||
let tr = &db.translates;
|
||
let name = match lang {
|
||
Lang::Rus => tr.rus,
|
||
Lang::Eng => tr.eng.unwrap_or(tr.rus),
|
||
};
|
||
|
||
Self {
|
||
key: db.key.to_string(),
|
||
lang: if name == tr.rus { Lang::Rus } else { lang },
|
||
name: name.to_string(),
|
||
}
|
||
}
|
||
}
|