Adds additional models, slightly more tests
This commit is contained in:
parent
2c5e84d836
commit
f947dd2912
@ -1,3 +1,4 @@
|
||||
DROP TABLE IF EXISTS actions;
|
||||
DROP TABLE IF EXISTS plans;
|
||||
|
||||
DROP FUNCTION IF EXISTS trigger_set_timestamp;
|
||||
|
@ -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();
|
||||
|
@ -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
1
go.mod
@ -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
1
go.sum
@ -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
27
main.go
@ -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 {
|
||||
|
@ -5,10 +5,10 @@ import (
|
||||
)
|
||||
|
||||
type Action struct {
|
||||
ID int64
|
||||
Description string
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
ActionID int64
|
||||
ActionDescription string
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
|
||||
func (m *Model) Actions() ([]*Action, error) {
|
||||
|
@ -1,13 +1,14 @@
|
||||
package models
|
||||
|
||||
type store interface {
|
||||
SelectActions() ([]*Action, error)
|
||||
type store interface {
|
||||
SelectActions() ([]*Action, error)
|
||||
SelectPlans() ([]*Plan, error)
|
||||
}
|
||||
|
||||
type Model struct {
|
||||
store
|
||||
}
|
||||
|
||||
func New(store store) *Model {
|
||||
return &Model{store: store}
|
||||
}
|
||||
|
||||
func New(store store) *Model {
|
||||
return &Model{store: store}
|
||||
}
|
||||
|
43
models/models_test.go
Normal file
43
models/models_test.go
Normal 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
14
models/plan.go
Normal 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
18
util/snake.go
Normal 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
69
util/snake_test.go
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user