Эх сурвалжийг харах

Working on handlers/orm refactoring

Andrea Fazzi 5 жил өмнө
parent
commit
d65228a55e
6 өөрчлөгдсөн 75 нэмэгдсэн , 77 устгасан
  1. 25 29
      handlers/handlers.go
  2. 18 6
      main.go
  3. 14 23
      orm/mappings.go
  4. 1 2
      orm/orm.go
  5. 2 2
      orm/orm_test.go
  6. 15 15
      orm/teacher.go

+ 25 - 29
handlers/handlers.go

@@ -8,6 +8,7 @@ import (
 	"net/http"
 	"path"
 	"path/filepath"
+	"reflect"
 	"runtime/debug"
 	"strconv"
 
@@ -51,19 +52,6 @@ var (
 		},
 		SigningMethod: jwt.SigningMethodHS256,
 	})
-
-	models = []string{
-		"teachers",
-		"classes",
-		"subjects",
-		"departments",
-		"activities",
-		"students",
-		"offices",
-		"administratives",
-		"documents",
-		"jobs",
-	}
 )
 
 func (pp PathPattern) RedirectPath(model string, id ...uint) string {
@@ -77,8 +65,16 @@ func (pp PathPattern) Path(model string) string {
 	return fmt.Sprintf(pp.PathPattern, model)
 }
 
+func modelName(s interface{}) string {
+	if t := reflect.TypeOf(s); t.Kind() == reflect.Ptr {
+		return t.Elem().Name()
+	} else {
+		return t.Name()
+	}
+}
+
 // Generate CRUD handlers for models
-func generateHandler(r *mux.Router, model string) {
+func generateHandler(r *mux.Router, model interface{}) {
 	var (
 		patterns []PathPattern = []PathPattern{
 			PathPattern{"/%s", "", []string{"GET"}},
@@ -108,30 +104,30 @@ func generateHandler(r *mux.Router, model string) {
 	// Install standard paths
 
 	for _, pattern := range patterns {
-		r.Handle(pattern.Path(model), jwtCookie.Handler(recoverHandler(modelHandler(model, pattern)))).Methods(pattern.Methods...)
+		r.Handle(pattern.Path(modelName(model)), jwtCookie.Handler(recoverHandler(modelHandler(modelName(model), pattern)))).Methods(pattern.Methods...)
 	}
 
 	// Install API paths
 
 	for _, pattern := range apiPatterns {
-		r.Handle(pattern.Path(model), jwtHeader.Handler(recoverHandler(modelHandler(model, pattern)))).Methods(pattern.Methods...)
+		r.Handle(pattern.Path(modelName(model)), jwtHeader.Handler(recoverHandler(modelHandler(modelName(model), pattern)))).Methods(pattern.Methods...)
 	}
 
 	if model == "documents" {
 		for _, pattern := range executePatterns {
-			r.Handle(pattern.Path(model), jwtCookie.Handler(recoverHandler(modelHandler(model, pattern)))).Methods(pattern.Methods...)
+			r.Handle(pattern.Path(modelName(model)), jwtCookie.Handler(recoverHandler(modelHandler(modelName(model), pattern)))).Methods(pattern.Methods...)
 		}
 	}
 
 	if model == "jobs" {
 		for _, pattern := range filePatterns {
-			r.Handle(pattern.Path(model), jwtCookie.Handler(recoverHandler(modelHandler(model, pattern)))).Methods(pattern.Methods...)
+			r.Handle(pattern.Path(modelName(model)), jwtCookie.Handler(recoverHandler(modelHandler(modelName(model), pattern)))).Methods(pattern.Methods...)
 		}
 	}
 
 }
 
-func Handlers() *mux.Router {
+func Handlers(models []interface{}) *mux.Router {
 	r := mux.NewRouter()
 
 	// Authentication
@@ -209,7 +205,7 @@ func get(w http.ResponseWriter, r *http.Request, model string, pattern PathPatte
 	if err != nil {
 		respondWithError(w, r, err)
 	} else {
-		data, err := getFn(mux.Vars(r))
+		data, err := getFn(mux.Vars(r), nil)
 		if err != nil {
 			renderer.Render[format](w, r, err)
 		} else {
@@ -221,12 +217,12 @@ func get(w http.ResponseWriter, r *http.Request, model string, pattern PathPatte
 
 func post(w http.ResponseWriter, r *http.Request, model string, pattern PathPattern) {
 	var (
-		data orm.IDer
+		data interface{}
 		err  error
 	)
 
 	respFormat := renderer.GetContentFormat(r)
-	postFn, err := orm.PostFunc(pattern.Path(model))
+	postFn, err := orm.GetFunc(pattern.Path(model))
 
 	if err != nil {
 		respondWithError(w, r, err)
@@ -239,10 +235,10 @@ func post(w http.ResponseWriter, r *http.Request, model string, pattern PathPatt
 				modelId, _ := strconv.Atoi(id)
 				http.Redirect(w, r, pattern.RedirectPath(model, uint(modelId)), http.StatusSeeOther)
 			} else {
-				http.Redirect(w, r, pattern.RedirectPath(model, data.GetID()), http.StatusSeeOther)
+				http.Redirect(w, r, pattern.RedirectPath(model, data.(orm.IDer).GetID()), http.StatusSeeOther)
 			}
 		} else {
-			renderer.Render[respFormat](w, r, data.GetID())
+			renderer.Render[respFormat](w, r, data.(orm.IDer).GetID())
 		}
 
 	}
@@ -251,15 +247,15 @@ func post(w http.ResponseWriter, r *http.Request, model string, pattern PathPatt
 
 func delete(w http.ResponseWriter, r *http.Request, model string, pattern PathPattern) {
 	var (
-		data orm.IDer
+		data interface{}
 		err  error
 	)
 
 	respFormat := renderer.GetContentFormat(r)
 
-	postFn, ok := orm.Post[pattern.Path(model)]
-	if !ok {
-		renderer.Render[r.URL.Query().Get("format")](w, r, fmt.Errorf("Can't find ORM function for path %s!", pattern.PathPattern))
+	postFn, err := orm.GetFunc(pattern.Path(model))
+	if err != nil {
+		renderer.Render[r.URL.Query().Get("format")](w, r, err)
 	}
 	data, err = postFn(mux.Vars(r), r)
 	if err != nil {
@@ -273,7 +269,7 @@ func delete(w http.ResponseWriter, r *http.Request, model string, pattern PathPa
 		w.Header().Set("Content-Type", "application/json")
 		json.NewEncoder(w).Encode(data)
 	} else {
-		renderer.Render[respFormat](w, r, data.GetID())
+		renderer.Render[respFormat](w, r, data.(orm.IDer).GetID())
 	}
 }
 

+ 18 - 6
main.go

@@ -26,13 +26,16 @@ const (
 	RetryTimeInterval = 5
 )
 
-func main() {
+var (
+	db  *gorm.DB
+	err error
 
-	var (
-		db  *gorm.DB
-		err error
-	)
+	models = []interface{}{
+		&orm.Teacher{},
+	}
+)
 
+func main() {
 	log.Println("Loading config file...")
 	err = config.ReadFile("config/config.yaml", config.Config)
 	if err != nil {
@@ -63,6 +66,11 @@ func main() {
 		orm.AutoMigrate()
 	}
 
+	log.Println("Map models <-> handlers")
+	if err := orm.MapHandlers(models); err != nil {
+		panic(err)
+	}
+
 	generator.Generators = make(map[string]generator.Generator)
 
 	log.Println("Initialize ListGenerator")
@@ -72,6 +80,10 @@ func main() {
 	generator.Generators["department"] = department.NewDepartmentGenerator(&generator.Config{ConfigT: *config.Config})
 
 	files, err := filepath.Glob("generator/generators/*")
+	if err != nil {
+		panic(err)
+	}
+
 	log.Println("Found the following generators...", files)
 	gTypes := make([]*orm.GeneratorType, 0)
 	for _, g := range files {
@@ -118,7 +130,7 @@ func main() {
 	c.Start()
 
 	log.Println("karmen is listening to port 3000...")
-	if err := http.ListenAndServe(":3000", handlers.LoggingHandler(os.Stdout, karmen_handlers.Handlers())); err != nil {
+	if err := http.ListenAndServe(":3000", handlers.LoggingHandler(os.Stdout, karmen_handlers.Handlers(models))); err != nil {
 		panic(err)
 	}
 

+ 14 - 23
orm/mappings.go

@@ -11,39 +11,39 @@ import (
 )
 
 var (
-	getFns  map[string]func(args map[string]string) (interface{}, error)
-	postFns map[string]func(args map[string]string, r *http.Request) (interface{}, error)
+	fns map[string]func(map[string]string, *http.Request) (interface{}, error)
 )
 
 func init() {
-	getFns = make(map[string]func(args map[string]string) (interface{}, error), 0)
+	fns = make(map[string]func(map[string]string, *http.Request) (interface{}, error), 0)
 }
 
-func MapModels(models []interface{}, handlers map[string]string) {
+func MapHandlers(models []interface{}) error {
 	for _, model := range models {
 
 		name := inflection.Plural(strings.ToLower(modelName(model)))
 
 		for p, action := range map[string]string{
-			"":            "GetAll",
+			"":            "ReadAll",
 			"create":      "Create",
-			"{id}":        "Get",
+			"{id}":        "Read",
 			"{id}/udpate": "Update",
+			"{id}/delete": "Delete",
 		} {
-			getFns[path.Join("/", name, p)] = reflect.ValueOf(model).MethodByName(action).Interface().(func(map[string]string) (interface{}, error))
-		}
-
-		for p, action := range map[string]string{
-			"{id}/udpate": "Update",
-		} {
-			getFns[path.Join("/", name, p)] = reflect.ValueOf(model).MethodByName(action).Interface().(func(map[string]string) (interface{}, error))
+			method := reflect.ValueOf(model).MethodByName(action)
+			if !method.IsValid() {
+				return fmt.Errorf("Action %s is not defined for model %s", action, name)
+			}
+			fns[path.Join("/", name, p)] = method.Interface().(func(map[string]string, *http.Request) (interface{}, error))
 		}
 
 	}
+
+	return nil
 }
 
 func GetFunc(path string) (GetFn, error) {
-	fn, ok := getFns[path]
+	fn, ok := fns[path]
 	if !ok {
 		return nil, fmt.Errorf("Can't map path %s to any model methods.", path)
 	}
@@ -51,15 +51,6 @@ func GetFunc(path string) (GetFn, error) {
 	return fn, nil
 }
 
-// // func PostFunc(path string) (PostFn, error) {
-// // 	fn, ok := Post[path]
-// // 	if !ok {
-// // 		return nil, fmt.Errorf("Can't map %s!", path)
-// // 	}
-
-// // 	return fn, nil
-// // }
-
 func GetNothing(args map[string]string) (interface{}, error) {
 	return nil, nil
 }

+ 1 - 2
orm/orm.go

@@ -44,8 +44,7 @@ type Desk struct {
 	Teacher  *Teacher
 }
 
-type GetFn func(map[string]string) (interface{}, error)
-type PostFn func(map[string]string, *http.Request) (IDer, error)
+type GetFn func(map[string]string, *http.Request) (interface{}, error)
 
 var currDB *gorm.DB
 

+ 2 - 2
orm/orm_test.go

@@ -114,7 +114,7 @@ func (t *testSuite) TestDeleteActivity() {
 }
 
 func (t *testSuite) TestGetTeacher() {
-	teacher, err := GetTeacher(map[string]string{"id": "1"})
+	teacher, err := new(Teacher).Read(map[string]string{"id": "1"})
 	t.Nil(err)
 	if !t.Failed() {
 		t.Equal("Amilcare", teacher.(*Teacher).Name)
@@ -161,7 +161,7 @@ func (t *testSuite) TestGetStudentAll() {
 }
 
 func (t *testSuite) TestGetTeachers() {
-	teachers, err := GetTeachers(map[string]string{})
+	teachers, err := new(Teacher).ReadAll(map[string]string{})
 	t.Nil(err)
 	t.Equal(11, len(teachers.([]*Teacher)))
 

+ 15 - 15
orm/teacher.go

@@ -69,7 +69,7 @@ func (t *Teacher) String() string {
 	return fmt.Sprintf("%s %s", t.Surname, t.Name)
 }
 
-func GetTeacher(args map[string]string) (interface{}, error) {
+func (t *Teacher) Read(args map[string]string) (interface{}, error) {
 	var teacher Teacher
 	if err := DB().First(&teacher, args["id"]).Error; err != nil {
 		return nil, err
@@ -77,6 +77,14 @@ func GetTeacher(args map[string]string) (interface{}, error) {
 	return &teacher, nil
 }
 
+func (t *Teacher) ReadAll(args map[string]string) (interface{}, error) {
+	var teachers []*Teacher
+	if err := DB().Order("surname,name").Find(&teachers).Error; err != nil {
+		return nil, err
+	}
+	return teachers, nil
+}
+
 func GetTeacherAll(args map[string]string) (interface{}, error) {
 	var teacher Teacher
 
@@ -127,14 +135,6 @@ func GetTeacherAll(args map[string]string) (interface{}, error) {
 	return &teacher, nil
 }
 
-func GetTeachers(args map[string]string) (interface{}, error) {
-	var teachers []*Teacher
-	if err := DB().Order("surname,name").Find(&teachers).Error; err != nil {
-		return nil, err
-	}
-	return teachers, nil
-}
-
 func GetTeachersAll(args map[string]string) (interface{}, error) {
 	var teachers []*Teacher
 	if err := DB().Order("surname,name").Find(&teachers).Error; err != nil {
@@ -202,8 +202,8 @@ func SaveTeacher(teacher interface{}) (interface{}, error) {
 	return teacher, nil
 }
 
-func UpdateTeacher(args map[string]string, r *http.Request) (IDer, error) {
-	teacher, err := GetTeacher(args)
+func (t *Teacher) Update(args map[string]string, r *http.Request) (IDer, error) {
+	teacher, err := t.Read(args)
 	if err != nil {
 		return nil, err
 	}
@@ -235,14 +235,14 @@ func UpdateTeacher(args map[string]string, r *http.Request) (IDer, error) {
 	if err != nil {
 		return nil, err
 	}
-	teacher, err = GetTeacher(args)
+	teacher, err = t.Read(args)
 	if err != nil {
 		return nil, err
 	}
 	return teacher.(*Teacher), nil
 }
 
-func AddTeacher(args map[string]string, r *http.Request) (IDer, error) {
+func (t *Teacher) AddTeacher(args map[string]string, r *http.Request) (IDer, error) {
 	teacher := new(Teacher)
 	err := renderer.Decode(teacher, r)
 	if err != nil {
@@ -270,8 +270,8 @@ func CreateTeacher(teacher *Teacher) (*Teacher, error) {
 	return teacher, nil
 }
 
-func DeleteTeacher(args map[string]string, r *http.Request) (IDer, error) {
-	teacher, err := GetTeacher(args)
+func (t *Teacher) Delete(args map[string]string, r *http.Request) (IDer, error) {
+	teacher, err := t.Read(args)
 	if err != nil {
 		return nil, err
 	}