Skip to content

Commit 46b5852

Browse files
committed
Initial commit with base features:
- docker-compose.yml for local development - Initial migrations for database - Example data for local development - Start/stop database scripts - Recipe list and single recipe pages
0 parents  commit 46b5852

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+15319
-0
lines changed

.gitignore

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Pipeline files until we have a remote concourse
2+
/pipeline
3+
4+
# Intellij files
5+
.idea
6+
7+
# Binaries for programs and plugins
8+
*.exe
9+
*.exe~
10+
*.dll
11+
*.so
12+
*.dylib
13+
14+
# Test binary, built with `go test -c`
15+
*.test
16+
17+
# Output of the go coverage tool, specifically when used with LiteIDE
18+
*.out
19+
20+
# Dependency directories (remove the comment below to include it)
21+
# vendor/

README.md

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Recipe Box
2+
3+
A React Redux website for storing recipes
4+
5+
# Local Development
6+
## Requirements
7+
* Docker
8+
* Go 1.12
9+
10+
## Running
11+
```bash
12+
go mod download
13+
14+
./scripts/run.sh
15+
```
16+
17+
# Running the tests
18+
```bash
19+
./scripts/test.sh
20+
```

db/docker-compose.yml

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
version: '3.7'
2+
services:
3+
db:
4+
image: mysql:5.7
5+
restart: always
6+
environment:
7+
MYSQL_DATABASE: 'db'
8+
MYSQL_USER: 'user'
9+
MYSQL_PASSWORD: 'password'
10+
MYSQL_ROOT_PASSWORD: 'password'
11+
ports:
12+
- '3306:3306'
13+
expose:
14+
- '3306'

go.mod

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
module github.com/iplay88keys/recipe-box
2+
3+
go 1.12
4+
5+
require (
6+
github.com/DATA-DOG/go-sqlmock v1.4.1
7+
github.com/go-sql-driver/mysql v1.5.0
8+
github.com/gorilla/mux v1.7.3
9+
github.com/onsi/ginkgo v1.11.0
10+
github.com/onsi/gomega v1.8.1
11+
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9 // indirect
12+
)

go.sum

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
github.com/DATA-DOG/go-sqlmock v1.4.1 h1:ThlnYciV1iM/V0OSF/dtkqWb6xo5qITT1TJBG1MRDJM=
2+
github.com/DATA-DOG/go-sqlmock v1.4.1/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
3+
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
4+
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
5+
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
6+
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
7+
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
8+
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
9+
github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw=
10+
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
11+
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
12+
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
13+
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
14+
github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw=
15+
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
16+
github.com/onsi/gomega v1.8.1 h1:C5Dqfs/LeauYDX0jJXIe2SWmwCbGzx9yF8C8xy3Lh34=
17+
github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
18+
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA=
19+
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
20+
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
21+
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
22+
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
23+
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9 h1:1/DFK4b7JH8DmkqhUk48onnSfrPzImPoVxuomtbT2nk=
24+
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
25+
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
26+
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
27+
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc=
28+
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
29+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
30+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
31+
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
32+
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
33+
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
34+
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
35+
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
36+
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

main.go

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package main
2+
3+
import (
4+
"database/sql"
5+
"flag"
6+
"fmt"
7+
"github.com/gorilla/mux"
8+
"github.com/iplay88keys/recipe-box/pkg/api"
9+
"github.com/iplay88keys/recipe-box/pkg/api/recipes"
10+
"github.com/iplay88keys/recipe-box/pkg/repositories"
11+
"os"
12+
"os/signal"
13+
"strconv"
14+
"strings"
15+
"syscall"
16+
17+
_ "github.com/go-sql-driver/mysql"
18+
)
19+
20+
func main() {
21+
var static string
22+
var port string
23+
var databaseURL string
24+
25+
flag.StringVar(&static, "static", "ui/build", "the directory to serve static files from")
26+
flag.StringVar(&port, "port", "8080", "the port to listen on")
27+
flag.StringVar(&databaseURL, "databaseURL", "", "the url for the database formatted as: $USER:$PASSWORD@tcp($HOST:$PORT)/$DATABASE")
28+
flag.Parse()
29+
30+
unquotedURL, err := strconv.Unquote(databaseURL)
31+
if err == nil {
32+
databaseURL = unquotedURL
33+
}
34+
db, err := sql.Open("mysql", strings.TrimSpace(databaseURL))
35+
if err != nil {
36+
panic(err)
37+
}
38+
39+
recipesRepo := repositories.NewRecipeRepository(db)
40+
ingredientsRepo := repositories.NewIngredientsRepository(db)
41+
stepsRepo := repositories.NewStepsRepository(db)
42+
43+
mux.NewRouter()
44+
a := api.New(&api.Config{
45+
Port: port,
46+
StaticDir: "ui/build",
47+
Endpoints: []api.Endpoint{
48+
recipes.ListRecipes(recipesRepo.List),
49+
recipes.GetRecipe(
50+
recipesRepo.Get,
51+
ingredientsRepo.GetForRecipe,
52+
stepsRepo.GetForRecipe,
53+
),
54+
},
55+
})
56+
57+
fmt.Printf("Serving at http://localhost:%s\n", port)
58+
fmt.Println("ctrl-c to quit")
59+
stopApi := a.Start()
60+
61+
defer stopApi()
62+
63+
blockUntilSigterm()
64+
}
65+
66+
func blockUntilSigterm() {
67+
sigs := make(chan os.Signal, 1)
68+
signal.Notify(sigs, syscall.SIGTERM, syscall.SIGINT)
69+
70+
<-sigs
71+
}

migrations/V1__Initial_Tables.sql

+116
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
CREATE TABLE users
2+
(
3+
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
4+
username VARCHAR(255) NOT NULL,
5+
email VARCHAR(255) NOT NULL,
6+
password_hash TEXT NOT NULL
7+
) ENGINE = INNODB;
8+
9+
CREATE TABLE cookbooks
10+
(
11+
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
12+
user_id INT NOT NULL,
13+
name VARCHAR(75) NOT NULL,
14+
15+
FOREIGN KEY (user_id)
16+
REFERENCES users (id)
17+
ON DELETE CASCADE
18+
) ENGINE = INNODB;
19+
20+
CREATE TABLE sections
21+
(
22+
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
23+
cookbook_id INT NOT NULL,
24+
name VARCHAR(75) NOT NULL,
25+
26+
FOREIGN KEY (cookbook_id)
27+
REFERENCES cookbooks (id)
28+
ON DELETE CASCADE
29+
) ENGINE = INNODB;
30+
31+
CREATE TABLE recipes
32+
(
33+
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
34+
creator INT NOT NULL,
35+
name VARCHAR(400) NOT NULL,
36+
description TEXT NOT NULL,
37+
servings INT NOT NULL,
38+
prep_time VARCHAR(50),
39+
cook_time VARCHAR(50),
40+
cool_time VARCHAR(50),
41+
total_time VARCHAR(50),
42+
source VARCHAR(400),
43+
44+
FOREIGN KEY (creator)
45+
REFERENCES users (id)
46+
ON DELETE CASCADE
47+
) ENGINE = INNODB;
48+
49+
CREATE TABLE ingredients
50+
(
51+
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
52+
name VARCHAR(50) NOT NULL
53+
) ENGINE = INNODB;
54+
55+
CREATE TABLE measurements
56+
(
57+
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
58+
name VARCHAR(50) NOT NULL
59+
) ENGINE = INNODB;
60+
61+
CREATE TABLE recipe_ingredients
62+
(
63+
recipe_id INT NOT NULL,
64+
ingredient_id INT NOT NULL,
65+
ingredient_no INT NOT NULL,
66+
amount VARCHAR(50),
67+
measurement_id INT,
68+
preparation varchar(255),
69+
70+
PRIMARY KEY (recipe_id, ingredient_id, ingredient_no),
71+
72+
FOREIGN KEY (recipe_id)
73+
REFERENCES recipes (id)
74+
ON DELETE CASCADE,
75+
FOREIGN KEY (ingredient_id)
76+
REFERENCES ingredients (id)
77+
ON DELETE CASCADE,
78+
FOREIGN KEY (measurement_id)
79+
REFERENCES measurements (id)
80+
ON DELETE CASCADE
81+
) ENGINE = INNODB;
82+
83+
CREATE TABLE recipe_steps
84+
(
85+
recipe_id INT NOT NULL,
86+
step_no INT NOT NULL,
87+
instructions text NOT NULL,
88+
89+
PRIMARY KEY (recipe_id, step_no),
90+
91+
FOREIGN KEY (recipe_id)
92+
REFERENCES recipes (id)
93+
ON DELETE CASCADE
94+
) ENGINE = INNODB;
95+
96+
CREATE TABLE recipe_locations
97+
(
98+
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
99+
recipe_id INT NOT NULL,
100+
cookbook_id INT,
101+
section_id INT,
102+
103+
FOREIGN KEY (recipe_id)
104+
REFERENCES recipes (id)
105+
ON DELETE CASCADE,
106+
FOREIGN KEY (cookbook_id)
107+
REFERENCES recipes (id)
108+
ON DELETE CASCADE,
109+
FOREIGN KEY (section_id)
110+
REFERENCES recipes (id)
111+
ON DELETE CASCADE
112+
) ENGINE = INNODB;
113+
114+
ALTER TABLE recipe_locations
115+
ADD CONSTRAINT CK_nulltest
116+
CHECK (cookbook_id IS NOT NULL OR section_id IS NOT NULL);

migrations/examples/example.sql

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
INSERT INTO users (username, email, password_hash)
2+
VALUES ("user", "[email protected]", PASSWORD("password")),
3+
("user2", "[email protected]", PASSWORD("password2"));
4+
5+
INSERT INTO cookbooks (user_id, name)
6+
VALUES (1, "Favorites"),
7+
(2, "Drinks");
8+
9+
INSERT INTO sections (name, cookbook_id)
10+
VALUES ("Sides", 1);
11+
12+
INSERT INTO recipes
13+
(creator,
14+
name,
15+
description,
16+
servings,
17+
prep_time,
18+
cook_time,
19+
cool_time,
20+
total_time,
21+
source)
22+
VALUES (1,
23+
"Root Beer Float",
24+
"Delicious drink for a hot summer day.",
25+
1, "5 m", NULL, NULL, "5 m", NULL),
26+
(2,
27+
"Nana's Beans",
28+
"Spruced up baked beans.",
29+
8, "10 m", NULL, NULL, "1-2 hrs",
30+
NULL);
31+
32+
INSERT INTO ingredients (name)
33+
VALUES ("Vanilla Ice Cream"),
34+
("Root Beer"),
35+
("Baked Beans"),
36+
("Bacon"),
37+
("Onion"),
38+
("Ketchup"),
39+
("Worcestershire Sauce"),
40+
("Brown Sugar"),
41+
("Yellow Mustard"),
42+
("BBQ Sauce");
43+
44+
INSERT INTO measurements (name)
45+
VALUES ("Scoop"),
46+
("Cup"),
47+
("Can"),
48+
("Tablespoon");
49+
50+
INSERT INTO recipe_ingredients (recipe_id, ingredient_id, ingredient_no, amount, measurement_id, preparation)
51+
VALUES (1, 1, 1, 1, 1, NULL),
52+
(1, 2, 2, NULL, NULL, NULL),
53+
(2, 3, 1, "2 28oz", NULL, NULL),
54+
(2, 4, 2, "3-4", NULL, "sliced"),
55+
(2, 5, 3, "2", 4, NULL),
56+
(2, 6, 4, "1", 4, NULL),
57+
(2, 7, 5, "2", 4, NULL),
58+
(2, 8, 6, "1", 4, NULL),
59+
(2, 9, 7, "2-3", 4, NULL);
60+
61+
INSERT INTO recipe_steps (recipe_id, step_no, instructions)
62+
VALUES (1, 1, "Place ice cream in glass."),
63+
(1, 2, "Top with Root Beer."),
64+
(2, 1, "Combine all ingredients in a pot."),
65+
(2, 2, "Simmer 1-2 hours.");
66+
67+
INSERT INTO recipe_locations (recipe_id, cookbook_id, section_id)
68+
VALUES (1, 2, NULL),
69+
(2, NULL, 1);

0 commit comments

Comments
 (0)