From f77bc38da5a63ab6a353e7eb466064c73caa590e Mon Sep 17 00:00:00 2001 From: Ruidy Nemausat Date: Wed, 18 Mar 2020 01:08:24 +0100 Subject: [PATCH] data: NewDB, NewContext, inject context into handlers, exits method in pagestore --- controllers/page.go | 29 +++++++++++++++++++---------- controllers/router.go | 9 ++++----- data/{psql.go => db.go} | 35 +++++++++++++++++++++++------------ data/files/doc.txt | 3 ++- data/pageQueries.go | 9 +++++++-- data/pageStore.go | 18 ++++++++++++++---- main.go | 29 +++++++++++++++++++++-------- models/page.go | 5 +++++ 8 files changed, 95 insertions(+), 42 deletions(-) rename data/{psql.go => db.go} (60%) diff --git a/controllers/page.go b/controllers/page.go index 2d80ec9..ce0c258 100644 --- a/controllers/page.go +++ b/controllers/page.go @@ -10,12 +10,13 @@ import ( // PageHandler will respond to requests using Handlers type PageHandler struct { - Pages data.PageStore + Ctx data.Context } //and add each actual handler as a method -func viewHandler(w http.ResponseWriter, r *http.Request, title string) { - p, err := models.LoadPage(title) - // p, err := ph.Pages.Get(1) +// func viewHandler(w http.ResponseWriter, r *http.Request, title string) { +func (ph PageHandler) view(w http.ResponseWriter, r *http.Request, title string) { + // p, err := models.LoadPage(title) + p, err := ph.Ctx.Pages.Get(title) if err != nil { http.Redirect(w, r, "/edit/"+title, http.StatusFound) return @@ -23,18 +24,26 @@ func viewHandler(w http.ResponseWriter, r *http.Request, title string) { views.Template(w, "view", p) } -func editHandler(w http.ResponseWriter, r *http.Request, title string) { - p, err := models.LoadPage(title) +func (ph PageHandler) edit(w http.ResponseWriter, r *http.Request, title string) { + // p, err := models.LoadPage(title) + p, err := ph.Ctx.Pages.Get(title) if err != nil { - p = models.NewPage(0, title, nil) + p = *models.NewPage(0, title, nil) } views.Template(w, "edit", p) } -func saveHandler(w http.ResponseWriter, r *http.Request, title string) { +func (ph PageHandler) save(w http.ResponseWriter, r *http.Request, title string) { body := r.FormValue("body") p := models.NewPage(0, title, []byte(body)) - err := p.Save() - checkError(err, w) + // err := p.Save() + + if !ph.Ctx.Pages.Exists(title) { + ph.Ctx.Pages.Add(*p) + } else { + ph.Ctx.Pages.Update(p.ID(), *p) + } + + // checkError(err, w) http.Redirect(w, r, "/view/"+title, http.StatusFound) } diff --git a/controllers/router.go b/controllers/router.go index 809425b..8c7b25a 100644 --- a/controllers/router.go +++ b/controllers/router.go @@ -6,12 +6,11 @@ import ( ) // Router dispatch the request to the corresponding route handlers. -func Router() { +func Router(ph PageHandler) { // http.HandleFunc("/", loveHandler) - // http.HandleFunc("/view/", makeHandler(ph.view)) - http.HandleFunc("/view/", makeHandler(viewHandler)) - http.HandleFunc("/edit/", makeHandler(editHandler)) - http.HandleFunc("/save/", makeHandler(saveHandler)) + http.HandleFunc("/view/", makeHandler(ph.view)) + http.HandleFunc("/edit/", makeHandler(ph.edit)) + http.HandleFunc("/save/", makeHandler(ph.save)) http.HandleFunc("/contact/", contactHandler) http.HandleFunc("/", homeHandler) } diff --git a/data/psql.go b/data/db.go similarity index 60% rename from data/psql.go rename to data/db.go index 4b165c5..234344a 100644 --- a/data/psql.go +++ b/data/db.go @@ -5,31 +5,29 @@ import ( "log" _ "github.com/lib/pq" // postgresql database package + "github.com/rjNemo/go-wiki/models" - "github.com/rjNemo/go-wiki/settings" ) -// UsePSQL read the connection parameters to establish a connection to the +// NewDB read the connection parameters to establish a connection to the // database. -func UsePSQL() *sql.DB { - connStr := settings.ConnStr - db, err := sql.Open("postgres", connStr) - if err != nil { - log.Fatal(err) - } - defer db.Close() +func NewDB(connection string) (*sql.DB, error) { - err = db.Ping() + db, err := sql.Open("postgres", connection) if err != nil { - log.Fatal(err) + return nil, err + } + + if err = db.Ping(); err != nil { + return nil, err } log.Println("Connection to database successfully established!") + return db, nil // store := NewUserStore(db) // store.CreateTable() - return db // u := models.TestUser() // store.Add(u) // log.Print(u) @@ -41,6 +39,19 @@ func UsePSQL() *sql.DB { // log.Println(store.Find("first_name", "John")) } +// Context registers the application data stores +type Context struct { + Pages PageStore + Users UserStore +} + +// NewContext returns a context instance +func NewContext(db *sql.DB) Context { + pageStore := NewPageStore(db) + userStore := NewUserStore(db) + return Context{Pages: pageStore, Users: userStore} +} + // Store interface defines the methods any store must satisfy type Store interface { CreateTable() diff --git a/data/files/doc.txt b/data/files/doc.txt index 4229cb3..4b62a15 100644 --- a/data/files/doc.txt +++ b/data/files/doc.txt @@ -1,4 +1,4 @@ - Type a term in the search bar. + Type a term in the search bar. If it already exist you will reach this page. @@ -10,4 +10,5 @@ Have fun ❤️ ❤️ ❤️ + \ No newline at end of file diff --git a/data/pageQueries.go b/data/pageQueries.go index 2e8af3f..e3f443c 100644 --- a/data/pageQueries.go +++ b/data/pageQueries.go @@ -6,13 +6,13 @@ const ( CreateTablePages = ` CREATE TABLE IF NOT EXISTS pages ( id SERIAL PRIMARY KEY, - title TEXT UNIQUE NOT NULL + title TEXT UNIQUE NOT NULL, body TEXT) ` // GetPage is the SQL command used to retrieve a user from the table GetPage = ` - SELECT * FROM pages WHERE id = $1; + SELECT * FROM pages WHERE title = $1; ` // GetAllPages is the SQL command used to retrieve all pages from the database. @@ -47,4 +47,9 @@ const ( WHERE id = $1 RETURNING *; ` + + // ExistsPage is the SQL command used to check whether a page from the database. + ExistsPage = ` + SELECT EXISTS(SELECT * FROM pages WHERE title = $1) + ` ) diff --git a/data/pageStore.go b/data/pageStore.go index a778a5b..b5c8e31 100644 --- a/data/pageStore.go +++ b/data/pageStore.go @@ -49,12 +49,12 @@ func (us PageStore) GetAll() ([]models.Page, error) { } // Get retrieves the page identified by 'id' from database -func (us PageStore) Get(uid int) (models.Page, error) { +func (us PageStore) Get(t string) (models.Page, error) { var id int var title string var body []byte - row := us.db.QueryRow(QueryGet, uid) + row := us.db.QueryRow(GetPage, t) switch err := row.Scan(&id, &title, &body); err { case sql.ErrNoRows: log.Println("No entry returned") @@ -70,7 +70,7 @@ func (us PageStore) Get(uid int) (models.Page, error) { // Add inserts a page in the database. func (us PageStore) Add(u models.Page) { id := 0 - err := us.db.QueryRow(QueryInsert, u.Title(), u.Body()).Scan(&id) + err := us.db.QueryRow(InsertPage, u.Title(), u.Body()).Scan(&id) if err != nil { log.Fatal(err) // too severe } @@ -79,7 +79,7 @@ func (us PageStore) Add(u models.Page) { // Update edits page identified by 'id' in the database func (us PageStore) Update(id int, u models.Page) { - res, err := us.db.Exec(QueryUpdate, id, u.Title(), u.Body()) + res, err := us.db.Exec(UpdatePage, id, u.Title(), u.Body()) if err != nil { log.Fatal(err) // too severe } @@ -107,6 +107,16 @@ func (us PageStore) Delete(id int) { } } +func (ps PageStore) Exists(title string) bool { + var e bool + err := ps.db.QueryRow(ExistsPage, title).Scan(&e) + log.Println("e:", e) + if err != nil { + log.Fatal(err) // too severe + } + return e //== title +} + // Find retrieves a page from the database using an expression // func (us PageStore) Find(k interface{}, v interface{}) ([]models.Page, error) { // var id, title int diff --git a/main.go b/main.go index d666618..16dffb1 100644 --- a/main.go +++ b/main.go @@ -10,15 +10,28 @@ import ( ) func main() { - data.UsePSQL() - startServer(settings.Port, controllers.Router) -} + // connect to db + db, err := data.NewDB(settings.ConnStr) + if err != nil { + log.Fatal(err) + } -func startServer(p string, r func()) { - log.Printf("Start Go-wiki server on http://localhost:%s", p) - port := ":" + p - r() + // register store and inject them in handlers + ctx := data.NewContext(db) + ctx.Pages.CreateTable() + // ctx.Users.CreateTable() + + ph := controllers.PageHandler{Ctx: ctx} + // uh := controllers.UserHandler{Users: UserStore} + + // startServer(, controllers.Router) + log.Printf("Start Go-wiki server on http://localhost:%s", settings.Port) + port := ":" + settings.Port + controllers.Router(ph) log.Fatal(http.ListenAndServe(port, nil)) } -// appBuilder +// func startServer(p string, r func()) { +// } + +// // appBuilder diff --git a/models/page.go b/models/page.go index 36f22ac..2f5b42b 100644 --- a/models/page.go +++ b/models/page.go @@ -11,6 +11,11 @@ type Page struct { body []byte } +// ID exposes Page's title field +func (p Page) ID() int { + return p.id +} + // Title exposes Page's title field func (p Page) Title() string { return p.title