Add ingredient methods

This commit is contained in:
Alessio 2024-11-09 23:02:18 -08:00
parent 981e1a663c
commit 7e03e15b3b
5 changed files with 158 additions and 23 deletions

2
doc/TODO.txt Normal file
View File

@ -0,0 +1,2 @@
TODO: figure-out-is-hidden
- what is it? Check in the existing foods database for items that are hidden i guess

View File

@ -1,7 +1,7 @@
package db package db
import ( import (
// "fmt" "fmt"
) )
type IngredientID uint64 type IngredientID uint64
@ -11,9 +11,9 @@ type Ingredient struct {
FoodID FoodID `db:"food_id"` FoodID FoodID `db:"food_id"`
RecipeID RecipeID `db:"recipe_id"` RecipeID RecipeID `db:"recipe_id"`
QuantityNumerator int64 `db:"quantity_numerator"` QuantityNumerator int64 `db:"quantity_numerator"`
QuantityDenominator int64 `db:"quantity_denominator"` QuantityDenominator int64 `db:"quantity_denominator"`
Units Units `db:"units"` Units UnitsID `db:"units"`
InRecipeID RecipeID `db:"in_recipe_id"` InRecipeID RecipeID `db:"in_recipe_id"`
ListOrder int64 `db:"list_order"` ListOrder int64 `db:"list_order"`
@ -24,3 +24,64 @@ type Ingredient struct {
// func (i Ingredient) String() string { // func (i Ingredient) String() string {
// return fmt.Sprintf("%s(%d)", f.Name, f.ID) // return fmt.Sprintf("%s(%d)", f.Name, f.ID)
// } // }
func (db *DB) SaveIngredient(i *Ingredient) {
if i.ID == IngredientID(0) {
println("creating---------")
// Do create
result, err := db.DB.NamedExec(`
insert into ingredients
(food_id, recipe_id, quantity_numerator, quantity_denominator, units, in_recipe_id, list_order, is_hidden)
values (nullif(:food_id, 0), nullif(:recipe_id, 0), :quantity_numerator, :quantity_denominator, :units, :in_recipe_id,
:list_order, :is_hidden)
`, i)
if err != nil {
panic(err)
}
// Update the ID
id, err := result.LastInsertId()
if err != nil {
panic(err)
}
i.ID = IngredientID(id)
} else {
println("updating---------")
// Do update
result, err := db.DB.NamedExec(`
update ingredients
set food_id=nullif(:food_id, 0),
recipe_id=nullif(:recipe_id, 0),
quantity_numerator=:quantity_numerator,
quantity_denominator=:quantity_denominator,
units=:units,
list_order=:list_order,
is_hidden=:is_hidden
where rowid = :rowid
`, i)
if err != nil {
panic(err)
}
count, err := result.RowsAffected()
if err != nil {
panic(err)
}
if count != 1 {
panic(fmt.Errorf("Got ingredient with ID (%d), so attempted update, but it doesn't exist", i.ID))
}
}
}
func (db *DB) DeleteIngredient(i Ingredient) {
result, err := db.DB.Exec(`delete from ingredients where rowid = ?`, i.ID)
if err != nil {
panic(err)
}
count, err := result.RowsAffected()
if err != nil {
panic(err)
}
if count != 1 {
panic(fmt.Errorf("tried to delete ingredient with ID (%d) but it doesn't exist", i.ID))
}
}

77
pkg/db/ingredient_test.go Normal file
View File

@ -0,0 +1,77 @@
package db_test
import (
"testing"
"github.com/go-test/deep"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
. "recipe_book/pkg/db"
)
func TestSaveAndLoadIngredient(t *testing.T) {
assert := assert.New(t)
require := require.New(t)
db := get_test_db()
// Setup
recipe := Recipe{
Name: "some Recipe",
Blurb: "Lorem Ispum dolor sit amet consquiter id blah blabh albha blahbla blahblahblh",
Instructions: RecipeInstructions{
"instr 1", "isntr 2", "instr3", "ins32gjkifw",
},
}
db.SaveRecipe(&recipe)
food := Food{
Name: "a food",
Cals: 10,
Carbs: 1,
Protein: 2,
}
db.SaveFood(&food)
// Create an ingredient on the recipe
ingr := Ingredient{
FoodID: food.ID,
QuantityNumerator: 3,
QuantityDenominator: 2,
Units: 1, // count
InRecipeID: recipe.ID,
ListOrder: 0,
}
assert.Equal(ingr.ID, IngredientID(0))
db.SaveIngredient(&ingr)
assert.NotEqual(ingr.ID, IngredientID(0))
// It should be added to the recipe at position 0
new_recipe, err := db.GetRecipeByID(recipe.ID)
assert.NoError(err)
require.Len(new_recipe.Ingredients, 1)
new_ingr := new_recipe.Ingredients[0]
if diff := deep.Equal(ingr, new_ingr); diff != nil {
t.Error(diff)
}
// Modify the ingredient
ingr.QuantityNumerator = 5
ingr.QuantityDenominator = 4
ingr.Units = 2
// Save it and reload the recipe
db.SaveIngredient(&ingr)
new_recipe, err = db.GetRecipeByID(recipe.ID)
assert.NoError(err)
require.Len(new_recipe.Ingredients, 1)
new_ingr = new_recipe.Ingredients[0]
if diff := deep.Equal(ingr, new_ingr); diff != nil {
t.Error(diff)
}
// Delete and reload-- should be gone
db.DeleteIngredient(ingr)
new_recipe, err = db.GetRecipeByID(recipe.ID)
assert.NoError(err)
require.Len(new_recipe.Ingredients, 0)
}

View File

@ -76,12 +76,6 @@ func (db *DB) SaveRecipe(r *Recipe) {
// TODO: recompute the computed_food // TODO: recompute the computed_food
} }
// func (db *DB) AddIngredientToRecipe(r Recipe, i *Ingredient) {
// result, err := db.DB.NamedExec(`
// insert into ingredients
// `, ingr)
// }
func (db *DB) GetRecipeByID(id RecipeID) (ret Recipe, err error) { func (db *DB) GetRecipeByID(id RecipeID) (ret Recipe, err error) {
err = db.DB.Get(&ret, ` err = db.DB.Get(&ret, `
select rowid, name, blurb, instructions select rowid, name, blurb, instructions
@ -89,12 +83,13 @@ func (db *DB) GetRecipeByID(id RecipeID) (ret Recipe, err error) {
where rowid = ? where rowid = ?
`, id) `, id)
if err != nil { if err != nil {
return Recipe{}, err return Recipe{}, fmt.Errorf("fetching recipe with ID %d: %w", id, err)
} }
// Load the ingredients // Load the ingredients
err = db.DB.Select(&ret.Ingredients, ` err = db.DB.Select(&ret.Ingredients, `
select food_id, recipe_id, quantity_numerator, quantity_denominator, units, list_order, is_hidden select rowid, ifnull(food_id, 0) food_id, ifnull(recipe_id, 0) recipe_id, quantity_numerator, quantity_denominator, units,
in_recipe_id, list_order, is_hidden
from ingredients from ingredients
where in_recipe_id = ? where in_recipe_id = ?
order by list_order asc order by list_order asc

View File

@ -52,19 +52,19 @@ create table units (rowid integer primary key,
abbreviation text not null unique check(length(abbreviation) != 0) abbreviation text not null unique check(length(abbreviation) != 0)
-- is_metric integer not null check(is_metric in (0, 1)) -- is_metric integer not null check(is_metric in (0, 1))
); );
insert into units(name, abbreviation) values insert into units(rowid, name, abbreviation) values
-- Count -- Count
('count', 'ct'), (1, 'count', 'ct'),
-- Mass -- Mass
('grams', 'g'), (2, 'grams', 'g'),
('pounds', 'lbs'), (3, 'pounds', 'lbs'),
('ounces', 'oz'), (4, 'ounces', 'oz'),
-- Volume -- Volume
('milliliters', 'mL'), (5, 'milliliters', 'mL'),
('cups', 'cups'), (6, 'cups', 'cups'),
('teaspoons', 'tsp'), (7, 'teaspoons', 'tsp'),
('tablespoons', 'tbsp'), (8, 'tablespoons', 'tbsp'),
('fluid ounces', 'fl-oz'); (9, 'fluid ounces', 'fl-oz');
create table ingredients (rowid integer primary key, create table ingredients (rowid integer primary key,
@ -82,7 +82,7 @@ create table ingredients (rowid integer primary key,
in_recipe_id integer references recipes(rowid) on delete cascade not null, in_recipe_id integer references recipes(rowid) on delete cascade not null,
list_order integer not null, list_order integer not null,
is_hidden integer not null default false, is_hidden integer not null default false,
unique (recipe_id, list_order) unique (in_recipe_id, list_order)
check((food_id is null) + (recipe_id is null) = 1) -- Exactly one should be active check((food_id is null) + (recipe_id is null) = 1) -- Exactly one should be active
) strict; ) strict;