package orm import ( "errors" "fmt" "net/http" "path" "strings" "git.andreafazzi.eu/andrea/oef/config" "git.andreafazzi.eu/andrea/oef/reflect" "github.com/jinzhu/gorm" _ "github.com/jinzhu/gorm/dialects/mysql" ) type IDer interface { GetID() uint } type GetFn func(*Database, map[string]string, http.ResponseWriter, *http.Request) (interface{}, error) type Database struct { Config *config.ConfigT models []interface{} _db *gorm.DB fns map[string]func(*Database, map[string]string, http.ResponseWriter, *http.Request) (interface{}, error) } func NewDatabase(config *config.ConfigT, models []interface{}) (*Database, error) { var err error db := new(Database) db.Config = config db.fns = make(map[string]func(*Database, map[string]string, http.ResponseWriter, *http.Request) (interface{}, error), 0) db.mapHandlers(models) db._db, err = gorm.Open("mysql", fmt.Sprintf("%s?%s", config.Orm.Connection, config.Orm.Options)) if err != nil { return nil, err } return db, err } func (db *Database) AutoMigrate() { if err := db._db.AutoMigrate(db.models...).Error; err != nil { panic(err) } } func (db *Database) GetUser(username, password string) (*User, error) { var user User if err := db._db.Where("username = ? AND password = ?", username, password).First(&user).Error; err != nil { return nil, errors.New("Authentication failed!") } return &user, nil } func (db *Database) DB() *gorm.DB { return db._db } func CreateCategories(db *Database) { for _, name := range categories { var category Category if err := db._db.FirstOrCreate(&category, Category{Name: name}).Error; err != nil { panic(err) } } } func (db *Database) mapHandlers(models []interface{}) error { for _, model := range models { name := reflect.ModelNameLowerPlural(model) for p, action := range map[string]string{ "": "ReadAll", "create/": "Create", "{id}": "Read", "{id}/update": "Update", "{id}/delete": "Delete", } { method := reflect.ModelMethod(model, action) if !method.IsValid() { return fmt.Errorf("Action %s is not defined for model %s", action, name) } joinedPath := path.Join("/", name, p) if strings.HasSuffix(p, "/") { joinedPath += "/" } db.fns[joinedPath] = method.Interface().(func(*Database, map[string]string, http.ResponseWriter, *http.Request) (interface{}, error)) } } return nil } func (db *Database) GetFunc(path string) (GetFn, error) { fn, ok := db.fns[path] if !ok { return nil, fmt.Errorf("Can't map path %s to any model methods.", path) } return fn, nil }