Skip to content

Commit

Permalink
Merge pull request #109 from suchapalaver/fix/support-private-fields-…
Browse files Browse the repository at this point in the history
…on-item-items-and-list-objects

fix: support private fields on item, items, and list objects
  • Loading branch information
suchapalaver authored Dec 31, 2023
2 parents 112ab70 + b4ddfe2 commit 50ea3a3
Show file tree
Hide file tree
Showing 9 changed files with 131 additions and 96 deletions.
4 changes: 2 additions & 2 deletions crates/api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,15 +159,15 @@ impl Display for ApiResponse {
Self::ItemAlreadyAdded(item) => writeln!(f, "\nitem already added: {item}"),
Self::Items(items) => {
writeln!(f)?;
for item in &items.collection {
for item in items.collection() {
writeln!(f, "{item}")?;
}
Ok(())
}
Self::JsonToSqlite => writeln!(f, "\nJSON to SQLite data store migration successful"),
Self::List(list) => {
writeln!(f)?;
for item in &list.items {
for item in list.items() {
writeln!(f, "{item}")?;
}
Ok(())
Expand Down
2 changes: 1 addition & 1 deletion crates/common/src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ pub fn user_wants_to_add_items_to_list() -> Answer {
pub fn user_wants_to_add_item_to_list(item: &Item) -> Option<bool> {
let res = Question::new(&format!(
"Do we need {}? (*y*, *n* for next item, *s* to skip to next section)",
item.name.as_str().to_lowercase()
item.name()
))
.acceptable(vec!["y", "n", "s"])
.until_acceptable()
Expand Down
25 changes: 21 additions & 4 deletions crates/common/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ use crate::recipes::Recipe;
/// * `recipes` - list of recipes of which the item is an ingredient
#[derive(Default, Serialize, Deserialize, Debug, Clone, PartialEq)]
pub struct Item {
pub name: Name,
pub section: Option<Section>,
pub recipes: Option<Vec<Recipe>>,
name: Name,
section: Option<Section>,
recipes: Option<Vec<Recipe>>,
}

impl Item {
pub fn new(name: impl Into<String>) -> Self {
Self {
name: Name(name.into()),
name: Name(name.into().to_lowercase()),
..Default::default()
}
}
Expand All @@ -29,11 +29,28 @@ impl Item {
&self.name
}

pub fn section(&self) -> Option<&Section> {
self.section.as_ref()
}

pub fn recipes(&self) -> Option<&Vec<Recipe>> {
self.recipes.as_ref()
}

pub fn recipes_mut(&mut self) -> Option<&mut [Recipe]> {
self.recipes.as_deref_mut()
}

pub fn with_section(mut self, section: impl Into<String>) -> Self {
self.section = Some(Section(section.into()));
self
}

pub fn with_recipes(mut self, recipes: &[Recipe]) -> Self {
self.recipes = Some(recipes.to_vec());
self
}

pub(crate) fn matches(&self, s: impl Into<String>) -> bool {
s.into().split(' ').all(|word| !self.name.0.contains(word))
}
Expand Down
30 changes: 18 additions & 12 deletions crates/common/src/items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ use crate::{

#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq)]
pub struct Items {
pub sections: Vec<Section>,
pub collection: Vec<Item>,
pub recipes: Vec<Recipe>,
sections: Vec<Section>,
collection: Vec<Item>,
recipes: Vec<Recipe>,
}

impl Load for Items {
Expand All @@ -35,6 +35,10 @@ impl Items {
Self::default()
}

pub fn collection(&self) -> impl Iterator<Item = &Item> {
self.collection.iter()
}

pub fn get_item_matches(&self, name: &str) -> impl Iterator<Item = &Item> {
self.collection
.iter()
Expand All @@ -51,7 +55,7 @@ impl Items {
if let Ok(i) = self
.collection
.iter()
.position(|x| x.name == Name::from(name))
.position(|x| x.name() == &Name::from(name))
.ok_or(ReadError::ItemNotFound)
{
self.collection.remove(i);
Expand All @@ -64,7 +68,7 @@ impl Items {
.iter()
.flat_map(|section| {
self.collection.iter().filter(|item| {
let Some(item_section) = &item.section else {
let Some(item_section) = item.section() else {
return false;
};
item_section.as_str().contains(section.as_str())
Expand All @@ -85,10 +89,12 @@ impl Items {

self.collection
.iter_mut()
.filter(|x| ingredients.contains(&x.name))
.for_each(|x| match x.recipes.as_mut() {
Some(recipes) => recipes.push(recipe.clone()),
None => x.recipes = Some(vec![recipe.clone()]),
.filter(|x| ingredients.contains(x.name()))
.for_each(|x| match x.recipes_mut() {
Some(recipes) => recipes.to_vec().push(recipe.clone()),
None => {
x.recipes_mut().replace(&mut [recipe.clone()]);
}
});

self.recipes.push(recipe);
Expand All @@ -105,9 +111,9 @@ impl Items {
self.recipes.remove(i);
}
for item in &mut self.collection {
if let Some(recipes) = item.recipes.as_mut() {
if let Some(recipes) = item.recipes_mut() {
if let Some(i) = recipes.iter().position(|recipe| recipe.as_str() == name) {
recipes.remove(i);
recipes.to_vec().remove(i);
}
}
}
Expand All @@ -123,7 +129,7 @@ impl Items {
.collection
.iter()
.filter(|item| {
let Some(recipes) = &item.recipes else {
let Some(recipes) = &item.recipes() else {
return false;
};
recipes.contains(&recipe)
Expand Down
52 changes: 39 additions & 13 deletions crates/common/src/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ use serde::{Deserialize, Serialize};

#[derive(Default, Serialize, Deserialize, Debug, Clone)]
pub struct List {
pub checklist: Vec<Item>,
pub recipes: Vec<Recipe>,
pub items: Vec<Item>,
checklist: Vec<Item>,
recipes: Vec<Recipe>,
items: Vec<Item>,
}

impl Load for List {
Expand All @@ -36,12 +36,39 @@ impl List {
Self::default()
}

pub fn with_checklist(mut self, checklist: Vec<Item>) -> Self {
self.checklist.extend(checklist);
self
}

pub fn with_recipes(mut self, recipes: Vec<Recipe>) -> Self {
self.recipes.extend(recipes);
self
}

pub fn with_items(mut self, items: Vec<Item>) -> Self {
self.items.extend(items);
self
}

pub fn checklist(&self) -> &Vec<Item> {
&self.checklist
}

pub fn recipes(&self) -> impl Iterator<Item = &Recipe> {
self.recipes.iter()
}

pub fn items(&self) -> &Vec<Item> {
&self.items
}

pub fn print(&self) {
if !self.checklist.is_empty() {
println!("Check if we need:");

self.checklist.iter().for_each(|item| {
println!("\t{}", item.name.as_str().to_lowercase());
println!("\t{}", item.name());
});
}
if !self.recipes.is_empty() {
Expand All @@ -55,7 +82,7 @@ impl List {
println!("groceries:");

self.items.iter().for_each(|item| {
println!("\t{}", item.name.as_str().to_lowercase());
println!("\t{}", item.name());
});
}
}
Expand All @@ -70,9 +97,9 @@ impl List {
.map(|section| {
let mut a: Vec<Item> = list_items
.iter()
.filter(|item| item.section.is_some())
.filter(|item| item.section().is_some())
.filter(|item| {
if let Some(item_sec) = &item.section {
if let Some(item_sec) = item.section() {
item_sec.as_str() == section
} else {
false
Expand All @@ -82,10 +109,9 @@ impl List {
.collect();

let b: Vec<Item> = groceries
.collection
.iter()
.collection()
.filter(|item| {
if let Some(item_sec) = &item.section {
if let Some(item_sec) = item.section() {
item_sec.as_str() == section && !a.contains(item)
} else {
false
Expand All @@ -102,7 +128,7 @@ impl List {
if !section.is_empty() {
for item in &section {
if !self.items.contains(item) {
if let Some(recipes) = &item.recipes {
if let Some(recipes) = &item.recipes() {
if recipes.iter().any(|recipe| self.recipes.contains(recipe)) {
self.add_item(item.clone());
}
Expand Down Expand Up @@ -137,7 +163,7 @@ impl List {
if let Ok(i) = self
.items
.iter()
.position(|x| x.name == Name::from(name))
.position(|x| x.name() == &Name::from(name))
.ok_or(ReadError::ItemNotFound)
{
self.items.remove(i);
Expand All @@ -153,7 +179,7 @@ impl List {
if let Ok(i) = self
.checklist
.iter()
.position(|x| x.name == Name::from(name))
.position(|x| x.name() == &Name::from(name))
.ok_or(ReadError::ItemNotFound)
{
self.checklist.remove(i);
Expand Down
16 changes: 9 additions & 7 deletions crates/persistence/src/json/migrate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ pub fn groceries(connection: &mut SqliteConnection, groceries: Items) -> Result<
let recipes_table = schema::recipes::table;
let sections_table = schema::sections::table;

for item in groceries.collection {
for item in groceries.collection() {
// add the item to the item table
let new_item = NewItem {
name: &item.name.to_string(),
name: item.name().as_str(),
};

diesel::insert_into(items_table)
Expand All @@ -62,14 +62,14 @@ pub fn groceries(connection: &mut SqliteConnection, groceries: Items) -> Result<

// get the item's item_id
let results = items_table
.filter(schema::items::dsl::name.eq(item.name.to_string()))
.filter(schema::items::dsl::name.eq(item.name().to_string()))
.load::<models::Item>(connection)?;

assert_eq!(results.len(), 1);

let item_id = results[0].id;

if let Some(item_recipes) = item.recipes {
if let Some(item_recipes) = item.recipes() {
// log the item_id in items_recipes
for recipe in item_recipes {
let new_recipe = NewRecipe {
Expand All @@ -96,11 +96,13 @@ pub fn groceries(connection: &mut SqliteConnection, groceries: Items) -> Result<
.values(&new_item_recipe)
.on_conflict_do_nothing()
.execute(connection)
.unwrap_or_else(|_| panic!("Error transferring item_recipe for {}", item.name));
.unwrap_or_else(|_| {
panic!("Error transferring item_recipe for {}", item.name())
});
}
}

if let Some(item_section) = item.section {
if let Some(item_section) = &item.section() {
// log the item_id in items_sections
let results = sections_table
.filter(schema::sections::dsl::name.eq(item_section.to_string()))
Expand All @@ -121,7 +123,7 @@ pub fn groceries(connection: &mut SqliteConnection, groceries: Items) -> Result<
.on_conflict_do_nothing()
.execute(connection)
.unwrap_or_else(|_| {
panic!("Error transferring item_section for {}", item.name)
panic!("Error transferring item_section for {}", item.name())
});
}
}
Expand Down
Loading

0 comments on commit 50ea3a3

Please sign in to comment.