Adds additional models, slightly more tests

This commit is contained in:
Deepak Mallubhotla 2020-12-27 19:14:27 -06:00
parent 2c5e84d836
commit f947dd2912
Signed by: deepak
GPG Key ID: 64BF53A3369104E7
12 changed files with 199 additions and 35 deletions

View File

@ -1,3 +1,4 @@
DROP TABLE IF EXISTS actions;
DROP TABLE IF EXISTS plans;
DROP FUNCTION IF EXISTS trigger_set_timestamp;

View File

@ -1,8 +1,19 @@
CREATE TABLE IF NOT EXISTS plans(
plan_id serial PRIMARY KEY,
plan_date DATE NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL
);
CREATE TABLE IF NOT EXISTS actions(
id serial PRIMARY KEY,
description VARCHAR (500),
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
action_id serial PRIMARY KEY,
action_description VARCHAR (500) NOT NULL,
estimated_chunks SMALLINT,
completed_chunks SMALLINT,
completed_on TIMESTAMP WITH TIME ZONE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL,
plan int REFERENCES plans(plan_id)
);
@ -18,3 +29,8 @@ CREATE TRIGGER set_updated
BEFORE UPDATE ON actions
FOR EACH ROW
EXECUTE PROCEDURE trigger_set_timestamp();
CREATE TRIGGER set_updated
BEFORE UPDATE ON plans
FOR EACH ROW
EXECUTE PROCEDURE trigger_set_timestamp();

View File

@ -8,11 +8,12 @@ import (
"os"
"gitea.deepak.science/deepak/gogmagog/config"
"gitea.deepak.science/deepak/gogmagog/models"
"gitea.deepak.science/deepak/gogmagog/util"
"github.com/golang-migrate/migrate/v4"
"github.com/golang-migrate/migrate/v4/database/postgres"
_ "github.com/golang-migrate/migrate/v4/source/file"
_ "github.com/jackc/pgx/v4/stdlib"
"gitea.deepak.science/deepak/gogmagog/models"
)
type postgresStore struct {
@ -56,14 +57,24 @@ func GetStore() *postgresStore {
if err := m.Up(); err != nil && err != migrate.ErrNoChange {
log.Fatalf("An error occurred while syncing the database.. %v", err)
}
db.MapperFunc(util.ToSnake)
return &postgresStore{db: db}
}
func (store *postgresStore) SelectActions() ([]*models.Action, error) {
actions := make([]*models.Action, 0)
err := store.db.Select(&actions, "SELECT id, description, created_at AS createdat, updated_at AS updatedat FROM actions")
err := store.db.Select(&actions, "SELECT action_id, action_description, created_at, updated_at FROM actions")
if err != nil {
return nil, err
}
return actions, nil
}
func (store *postgresStore) SelectPlans() ([]*models.Plan, error) {
plans := make([]*models.Plan, 0)
err := store.db.Select(&plans, "SELECT plan_id, plan_date FROM plans")
if err != nil {
return nil, err
}
return plans, nil
}

1
go.mod
View File

@ -7,4 +7,5 @@ require (
github.com/jackc/pgx/v4 v4.10.1
github.com/jmoiron/sqlx v1.2.0
github.com/spf13/viper v1.7.1
github.com/stretchr/testify v1.5.1
)

1
go.sum
View File

@ -399,6 +399,7 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=

27
main.go
View File

@ -5,7 +5,6 @@ import (
"gitea.deepak.science/deepak/gogmagog/db"
"gitea.deepak.science/deepak/gogmagog/models"
"log"
"net/http"
)
func main() {
@ -28,26 +27,16 @@ func main() {
log.Print("created model")
}
http.Handle("/static/", http.FileServer(http.Dir("public")))
http.HandleFunc("/actions/", HandleAction)
log.Fatal(http.ListenAndServe(":"+port, nil))
}
func ShowCompleteActions(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(r.URL.Path))
}
func HandleAction(w http.ResponseWriter, r *http.Request) {
var message string
id := r.URL.Path[len("/actions/"):]
if r.Method == "GET" {
message = "Get the action " + id
acts, acterr := m.Actions()
if acterr != nil {
log.Fatal("whoopsies", acterr)
} else {
message = r.Method + " the action " + id
log.Printf("Got %d actions", len(acts))
for i, act := range acts {
log.Printf("%d: %v", i, act)
}
w.Write([]byte(message))
}
}
func Hello() string {

View File

@ -5,8 +5,8 @@ import (
)
type Action struct {
ID int64
Description string
ActionID int64
ActionDescription string
CreatedAt time.Time
UpdatedAt time.Time
}

View File

@ -2,6 +2,7 @@ package models
type store interface {
SelectActions() ([]*Action, error)
SelectPlans() ([]*Plan, error)
}
type Model struct {

43
models/models_test.go Normal file
View File

@ -0,0 +1,43 @@
package models_test
import (
"gitea.deepak.science/deepak/gogmagog/models"
"github.com/stretchr/testify/assert"
"testing"
)
type store interface {
SelectActions() ([]*models.Action, error)
SelectPlans() ([]*models.Plan, error)
}
type multiStore struct {
actions []*models.Action
plans []*models.Plan
}
func (ms *multiStore) SelectActions() ([]*models.Action, error) {
return ms.actions, nil
}
func (ms *multiStore) SelectPlans() ([]*models.Plan, error) {
return ms.plans, nil
}
func TestModelActions(t *testing.T) {
assert := assert.New(t)
a1 := &models.Action{ActionID: 3}
a2 := &models.Action{ActionID: 4}
p := &models.Plan{PlanID: 6}
ss := &multiStore{
[]*models.Action{a1, a2},
[]*models.Plan{p}}
m := models.New(ss)
actions, err := m.Actions()
assert.Nil(err)
assert.Equal(2, len(actions))
plans, err := m.Plans()
assert.Nil(err)
assert.Equal(1, len(plans))
}

14
models/plan.go Normal file
View File

@ -0,0 +1,14 @@
package models
import (
"time"
)
type Plan struct {
PlanID int64
PlanDate time.Time
}
func (m *Model) Plans() ([]*Plan, error) {
return m.SelectPlans()
}

18
util/snake.go Normal file
View File

@ -0,0 +1,18 @@
package util
import "unicode"
func ToSnake(in string) string {
runes := []rune(in)
length := len(runes)
var out []rune
for i := 0; i < length; i++ {
if i > 0 && unicode.IsUpper(runes[i]) && ((i+1 < length && unicode.IsLower(runes[i+1])) || unicode.IsLower(runes[i-1])) {
out = append(out, '_')
}
out = append(out, unicode.ToLower(runes[i]))
}
return string(out)
}

69
util/snake_test.go Normal file
View File

@ -0,0 +1,69 @@
package util_test
import (
"strings"
"testing"
"gitea.deepak.science/deepak/gogmagog/util"
)
// from https://github.com/paultyng/snake
type SnakeTest struct {
input string
output string
}
var tests = []SnakeTest{
{"a", "a"},
{"snake", "snake"},
{"A", "a"},
{"ID", "id"},
{"MOTD", "motd"},
{"Snake", "snake"},
{"SnakeTest", "snake_test"},
{"SnakeID", "snake_id"},
{"SnakeIDGoogle", "snake_id_google"},
{"LinuxMOTD", "linux_motd"},
{"OMGWTFBBQ", "omgwtfbbq"},
{"omg_wtf_bbq", "omg_wtf_bbq"},
{"APIResponse", "api_response"},
}
func TestToSnake(t *testing.T) {
for _, test := range tests {
if util.ToSnake(test.input) != test.output {
t.Errorf(`ToSnake("%s"), wanted "%s", got \%s"`, test.input, test.output, util.ToSnake(test.input))
}
}
}
var benchmarks = []string{
"a",
"snake",
"A",
"Snake",
"SnakeTest",
"SnakeID",
"SnakeIDGoogle",
"LinuxMOTD",
"OMGWTFBBQ",
"omg_wtf_bbq",
"APIResponse",
}
func BenchmarkToSnake(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, input := range benchmarks {
util.ToSnake(input)
}
}
}
func BenchmarkToLower(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, input := range benchmarks {
strings.ToLower(input)
}
}
}