Code Monkey home page Code Monkey logo

suchapalaver / gust Goto Github PK

View Code? Open in Web Editor NEW
6.0 1.0 0.0 601 KB

Built in Rust and leveraging Docker, JSON, and SQLite (with future integration of a GraphQL API), 'gust' simplifies the process of preserving your recipes and creating comprehensive grocery shopping lists.

Home Page: https://github.com/suchapalaver/gust

License: MIT License

Rust 98.49% Dockerfile 0.23% Makefile 1.28%
rust rust-lang serde serde-json clap beginner-project beginner-friendly error-handling deserialization command-line-app rust-language custom-error traits docker sqlite

gust's Introduction

gust: rust-powered grocery list creator

use gust to add recipes and grocery items to a local database, making putting together shopping lists super quick.

summary

prerequisites

The main prerequisite to get started using this application is Docker. Docker allows you to build an image of an application and run application containers, allowing you to use an application such as gust without needing to install the Rust programming language, database software, or other dependencies on your computer.

All you need is to install Docker.


docs

overview

gust design diagram


getting started

build the docker image

docker build --tag gust --file Dockerfile .

help menu

docker run --rm gust

or:

cargo run -- -h    

fetch a recipe and save it to the database

docker run --rm -v gust:/app gust fetch --url https://www.bbc.co.uk/food/recipes/vegetable_noodle_pancake_22079

read the recipes in the database

docker run --rm -v gust:/app gust read recipes

read a recipe's ingredients

docker run --rm -v gust:/app gust read --recipe 'vegetable noodle pancake'

add a recipe to the list

docker run --rm -v gust:/app gust add list --recipe 'vegetable noodle pancake'

read the items on the list

docker run --rm -v gust:/app gust read list

clear the list

docker run --rm -v gust:/app gust update list clear

gust's People

Contributors

suchapalaver avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

gust's Issues

Make `...or_insert` methods make more sense

Below is just one example where we're inefficiently inserting using on_conflict_do_nothing to ensure that an item is present in our store, a good example of the kind of path of least resistance that doesn’t lead to a good place.

//! crates/persistence/src/sqlite/mod.rs

fn get_or_insert_item(
    &mut self,
    connection: &mut SqliteConnection,
    name: &str,
) -> Result<i32, StoreError> {
    diesel::insert_into(schema::items::table)
        .values(NewItem { name })
        .on_conflict_do_nothing()
        .execute(connection)?;

    let item_query = schema::items::table.filter(schema::items::dsl::name.eq(name));

    Ok(item_query
        .select(schema::items::dsl::id)
        .first(connection)?)
}

Sort out command line

Right now clap isn't being used particularly correctly. Let's aim for arguments like the following for a start:
cargo run -- recipe new "tofu chicken rice" --ingredients tofu rice chicken garlic
And have the same minus the --ingredients flag run a default that asks the user for ingredients input

Support NYT recipes

gust currently only supports requests for recipes from the BBC Food website.

Improved error handling

Errors aren’t specific enough right now. Good example if there’s some problem with the JSON files.

Support updating section for items

Currently we have a rigid system using:

pub const SECTIONS: [&str; 5] = ["fresh", "pantry", "protein", "dairy", "freezer"];

This should be flexible according the user.

Make fetching and adding recipes idempotent

Adding the same recipe, for example by running make fetch url=https://www.bbc.co.uk/food/recipes/vegetable_noodle_pancake_22079 twice will result in something like this:

2023-12-28T18:15:32.603913Z ERROR api: API dispatch, error: StoreError(DBQuery(DatabaseError(UniqueViolation, "UNIQUE constraint failed: items_recipes.item_id, items_recipes.recipe_id")))
    at crates/api/src/lib.rs:104

a next step if you're into it--subcommands using clap

I'm not a huge fan of running through asking what operation you want to perform. Maybe you could look into using subcommands with the clap crate, so if you want to add a recipe to the library you don't have to enter n a bunch of times.

You could also make a help subcommand that prints some info and maybe with no subcommand you can run the same process you have.

Once you have them broken into subcommands you'll see that running one after the other looks much cleaner too.

Better organization

For example Groceries contains write_to_file, read_from_file, and get_sections. These aren't really specific to the impl for a given instance of Groceries. It feels like maybe these should be made into a module rather than an impl block.

A lot of things are just strings. These could made type safe by creating types for these things and using shrinkwraprs to retain all the expected methods from string.

For example you have:

struct GroceriesSection {
    section: String,
    items: Vec<String>,
}
struct Recipe {
    recipe: String,
    ingredients: Vec<String>,
}
struct ShoppingList {
    recipes_msg: String,
    recipes: Vec<String>,
    checklist_msg: String,
    checklist: Vec<String>,
    list_msg: String,
    list: Vec<String>,
}

Here the types do not make clear which items are used in which places. For example GroceriesSection::String is totally unrelated to the items in Recipe::ingredients. However GroceriesSection::items is the same. So rather than all of these being just String you could have types like:

#[derive(Shrinkwrap)]
struct RecipeName(String);
#[derive(Shrinkwrap)]
struct Ingredient{ name: String }
``
etc. (using shrinkwraprs 3)
This would make things like `ShoppingList` much easier to understand by looking at the struct.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.