diff --git a/lib/controller.go b/controller/controller.go similarity index 50% rename from lib/controller.go rename to controller/controller.go index 7cfd9a5..a8a0ed5 100644 --- a/lib/controller.go +++ b/controller/controller.go @@ -1,28 +1,18 @@ -package lib +package controller -import ( - "database/sql" - "net/http" -) +import "net/http" // Controller Super-struct for all controllers. type Controller struct { - Db *sql.DB Params []string } -// ControllerInterface Interface to satisfy being a controller. -type ControllerInterface interface { +// Interface Interface to satisfy being a controller. +type Interface interface { Run(w http.ResponseWriter, r *http.Request) - SetDb(db *sql.DB) SetParams(p []string) } -// SetDb Set the database pointer -func (c *Controller) SetDb(db *sql.DB) { - c.Db = db -} - // SetParams Set the current parameters on the controller. func (c *Controller) SetParams(p []string) { c.Params = p diff --git a/controller/error.go b/controller/error.go index f0837ed..9b2c388 100644 --- a/controller/error.go +++ b/controller/error.go @@ -1,14 +1,13 @@ package controller import ( - "journal/lib" "net/http" "text/template" ) // Error Display a 404 type Error struct { - lib.Controller + Controller } // Run Error diff --git a/controller/index.go b/controller/index.go index 3986bd1..1c93759 100644 --- a/controller/index.go +++ b/controller/index.go @@ -1,7 +1,6 @@ package controller import ( - "journal/lib" "journal/model" "net/http" "text/template" @@ -9,7 +8,7 @@ import ( // Index Handle displaying all blog entries type Index struct { - lib.Controller + Controller } type indexData struct { @@ -21,7 +20,6 @@ type indexData struct { func (c *Index) Run(w http.ResponseWriter, r *http.Request) { js := model.Journals{} - js.SetDb(c.Db) js.FetchAll() data := indexData{js.Journals, false} query := r.URL.Query() diff --git a/controller/new.go b/controller/new.go index 74ed182..dbaf1bd 100644 --- a/controller/new.go +++ b/controller/new.go @@ -1,7 +1,6 @@ package controller import ( - "journal/lib" "journal/model" "net/http" "text/template" @@ -9,7 +8,7 @@ import ( // New Handle creating a new entry type New struct { - lib.Controller + Controller } // Run NewC @@ -34,7 +33,6 @@ func (c *New) Run(w http.ResponseWriter, r *http.Request) { } js := model.Journals{} - js.SetDb(c.Db) js.Create(0, model.Slugify(r.FormValue("title")), r.FormValue("title"), r.FormValue("date"), r.FormValue("content")) http.Redirect(w, r, "/?saved=1", 302) diff --git a/controller/view.go b/controller/view.go index a20e713..9979590 100644 --- a/controller/view.go +++ b/controller/view.go @@ -1,7 +1,6 @@ package controller import ( - "journal/lib" "journal/model" "net/http" "text/template" @@ -9,7 +8,7 @@ import ( // View Handle displaying individual entry type View struct { - lib.Controller + Controller } type viewData struct { @@ -20,7 +19,6 @@ type viewData struct { func (c *View) Run(w http.ResponseWriter, r *http.Request) { js := model.Journals{} - js.SetDb(c.Db) j := js.FindBySlug(c.Params[0]) if j.ID == 0 { diff --git a/lib/error.go b/lib/error.go deleted file mode 100644 index 64ebcce..0000000 --- a/lib/error.go +++ /dev/null @@ -1,10 +0,0 @@ -package lib - -import "log" - -// CheckErr Check and fatal if applicable -func CheckErr(err error) { - if err != nil { - log.Fatal("Error reported: ", err) - } -} diff --git a/lib/router.go b/lib/router.go index 048b751..d538a4a 100644 --- a/lib/router.go +++ b/lib/router.go @@ -1,7 +1,7 @@ package lib import ( - "database/sql" + "journal/controller" "log" "net/http" "os" @@ -13,18 +13,18 @@ type Route struct { method string uri string matchable bool - controller ControllerInterface + controller controller.Interface } // Router Contian routes type Router struct { - db *sql.DB - err ControllerInterface + err controller.Interface routes []Route + server *Server } // Add A new route -func (m *Router) Add(t string, u string, a bool, c ControllerInterface) { +func (m *Router) Add(t string, u string, a bool, c controller.Interface) { r := Route{t, u, a, c} m.routes = append(m.routes, r) } @@ -46,7 +46,6 @@ func (m *Router) ServeHTTP(w http.ResponseWriter, r *http.Request) { for _, route := range m.routes { if r.URL.Path == route.uri && (r.Method == route.method || (r.Method == "" && route.method == "GET")) { - route.controller.SetDb(m.db) route.controller.Run(w, r) return } @@ -56,7 +55,6 @@ func (m *Router) ServeHTTP(w http.ResponseWriter, r *http.Request) { matched, _ := regexp.MatchString(route.uri, r.URL.Path) if matched && (r.Method == route.method || (r.Method == "" && route.method == "GET")) { re := regexp.MustCompile(route.uri) - route.controller.SetDb(m.db) route.controller.SetParams(re.FindAllString(r.URL.Path, -1)) route.controller.Run(w, r) return @@ -67,12 +65,9 @@ func (m *Router) ServeHTTP(w http.ResponseWriter, r *http.Request) { m.err.Run(w, r) } -// SetDb Set the db -func (m *Router) SetDb(db *sql.DB) { - m.db = db -} +// NewRouter Create a new router +func NewRouter(s *Server, e controller.Interface) Router { + var r []Route -// SetErr Set the err controller -func (m *Router) SetErr(err ControllerInterface) { - m.err = err + return Router{e, r, s} } diff --git a/lib/server.go b/lib/server.go new file mode 100644 index 0000000..37cdf46 --- /dev/null +++ b/lib/server.go @@ -0,0 +1,57 @@ +package lib + +import ( + "database/sql" + "journal/controller" + "journal/model" + "log" + "net/http" +) + +// Server Contain the server +type Server struct { + db *sql.DB + router Router +} + +// CheckErr Check and fatal if applicable +func (s Server) CheckErr(err error) { + if err != nil { + log.Fatal("Error reported: ", err) + } +} + +func (s *Server) createDb() { + err := model.JournalCreateTable() + s.CheckErr(err) + log.Println("Database created") +} + +func (s *Server) initRouter() { + s.router = NewRouter(s, &controller.Error{}) + s.router.Add("GET", "/", false, &controller.Index{}) + s.router.Add("GET", "/new", false, &controller.New{}) + s.router.Add("POST", "/new", false, &controller.New{}) + s.router.Add("GET", "\\/([\\w\\-]+)", true, &controller.View{}) +} + +// Run Run the server +func (s *Server) Run(mode string, port string) { + if mode == "create" { + s.createDb() + } else { + s.initRouter() + s.serve(port) + } + s.db.Close() +} + +func (s *Server) serve(port string) { + log.Printf("Listening on port %s\n", port) + log.Fatal(http.ListenAndServe(":"+port, &s.router)) +} + +// NewServer Create an instance of the server +func NewServer() Server { + return Server{} +} diff --git a/main.go b/main.go index b01c38a..2889da5 100644 --- a/main.go +++ b/main.go @@ -1,19 +1,13 @@ package main import ( - "database/sql" "flag" "fmt" - "journal/controller" "journal/lib" - "log" - "net/http" "os" - - _ "github.com/mattn/go-sqlite3" ) -var db *sql.DB +var server lib.Server func main() { const version = "0.1" @@ -27,40 +21,9 @@ func main() { // Set CWD os.Chdir(os.Getenv("GOPATH")) - - // Load database - newdb, err := sql.Open("sqlite3", "./data/journal.db") - db = newdb - lib.CheckErr(err) fmt.Printf("Journal v%s...\n-------------------\n\n", version) - if *mode == "create" { - - _, err := db.Exec("CREATE TABLE `journal` (" + - "`id` INTEGER PRIMARY KEY AUTOINCREMENT, " + - "`slug` VARCHAR(255) NOT NULL, " + - "`title` VARCHAR(255) NOT NULL, " + - "`date` DATE NOT NULL, " + - "`content` TEXT NOT NULL" + - ")") - lib.CheckErr(err) - db.Close() - log.Println("Database created") - - } else { - - m := &lib.Router{} - m.SetDb(db) - m.SetErr(&controller.Error{}) - m.Add("GET", "/", false, &controller.Index{}) - m.Add("GET", "/new", false, &controller.New{}) - m.Add("POST", "/new", false, &controller.New{}) - m.Add("GET", "\\/([\\w\\-]+)", true, &controller.View{}) - - log.Printf("Listening on port %s\n", *port) - log.Fatal(http.ListenAndServe(":"+*port, m)) - - db.Close() - - } + // Create the server + server = lib.NewServer() + server.Run(*mode, *port) } diff --git a/model/journal.go b/model/journal.go index 29f1764..c968f58 100644 --- a/model/journal.go +++ b/model/journal.go @@ -2,16 +2,20 @@ package model import ( "database/sql" - "journal/lib" + "log" + "os" "regexp" "strings" + + _ "github.com/mattn/go-sqlite3" // SQLite 3 driver ) const table = "journal" +var db *sql.DB + // Journals Collection of Journals type Journals struct { - db *sql.DB Journals []Journal } @@ -38,8 +42,7 @@ func (js *Journals) Create(id int, slug string, title string, date string, conte // FetchAll Get all journals func (js *Journals) FetchAll() { - rows, err := js.db.Query("SELECT * FROM `" + table + "` ORDER BY `date` DESC") - lib.CheckErr(err) + rows, _ := db.Query("SELECT * FROM `" + table + "` ORDER BY `date` DESC") defer rows.Close() for rows.Next() { @@ -50,8 +53,7 @@ func (js *Journals) FetchAll() { // FindBySlug Find a journal by slug. func (js *Journals) FindBySlug(s string) Journal { // Attempt to find the entry - rows, err := js.db.Query("SELECT * FROM `"+table+"` WHERE `slug` = ?", strings.Replace(s, "/", "", 1)) - lib.CheckErr(err) + rows, _ := db.Query("SELECT * FROM `"+table+"` WHERE `slug` = ?", strings.Replace(s, "/", "", 1)) defer rows.Close() for rows.Next() { @@ -72,28 +74,22 @@ func (js *Journals) load(rows *sql.Rows) { var date string var content string - err := rows.Scan(&id, &slug, &title, &date, &content) - lib.CheckErr(err) - + rows.Scan(&id, &slug, &title, &date, &content) js.Create(id, slug, title, date, content) } func (js *Journals) save(j Journal) Journal { var stmt *sql.Stmt - var err error var res sql.Result if j.ID == 0 { - stmt, err = js.db.Prepare("INSERT INTO `" + table + "` (`slug`, `title`, `date`, `content`) VALUES(?,?,?,?)") - lib.CheckErr(err) - res, err = stmt.Exec(j.Slug, j.Title, j.Date, j.Content) + stmt, _ = db.Prepare("INSERT INTO `" + table + "` (`slug`, `title`, `date`, `content`) VALUES(?,?,?,?)") + res, _ = stmt.Exec(j.Slug, j.Title, j.Date, j.Content) } else { - stmt, err = js.db.Prepare("UPDATE `" + table + "` SET `slug` = ?, `title` = ?, `date` = ?, `content` = ? WHERE `id` = ?") - lib.CheckErr(err) - res, err = stmt.Exec(j.Slug, j.Title, j.Date, j.Content, j.ID) + stmt, _ = db.Prepare("UPDATE `" + table + "` SET `slug` = ?, `title` = ?, `date` = ?, `content` = ? WHERE `id` = ?") + res, _ = stmt.Exec(j.Slug, j.Title, j.Date, j.Content, j.ID) } // Store insert ID - lib.CheckErr(err) if j.ID == 0 { id, _ := res.LastInsertId() j.ID = int(id) @@ -102,11 +98,6 @@ func (js *Journals) save(j Journal) Journal { return j } -// SetDb Set the database. -func (js *Journals) SetDb(db *sql.DB) { - js.db = db -} - // GetDate Get the friendly date for the Journal func (j Journal) GetDate() string { re := regexp.MustCompile("\\d{4}\\-\\d{2}\\-\\d{2}") @@ -120,9 +111,31 @@ func (j Journal) GetDate() string { return strings.Join(dateArr, "/") } +// JournalCreateTable Create the actual table +func JournalCreateTable() error { + _, err := db.Exec("CREATE TABLE `journal` (" + + "`id` INTEGER PRIMARY KEY AUTOINCREMENT, " + + "`slug` VARCHAR(255) NOT NULL, " + + "`title` VARCHAR(255) NOT NULL, " + + "`date` DATE NOT NULL, " + + "`content` TEXT NOT NULL" + + ")") + + return err +} + // Slugify Utility to convert a string into a slug func Slugify(s string) string { re := regexp.MustCompile("[\\W+]") return strings.ToLower(re.ReplaceAllString(s, "-")) } + +func init() { + var err error + db, err = sql.Open("sqlite3", "./data/journal.db") + if err != nil { + log.Print(err) + os.Exit(1) + } +}