-
Notifications
You must be signed in to change notification settings - Fork 77
Use Gorm with Blueprint
Joseph Spurrier edited this page Sep 15, 2016
·
2 revisions
To use gorm with Blue Jay, you can add this file to blue-jay/core/storage/driver/gorm/gorm.go:
// Package gorm provides a wrapper around the jinzhu/gorm package.
package gorm
import (
"fmt"
"strings"
"sync"
gm "github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
)
// *****************************************************************************
// Thread-Safe Configuration
// *****************************************************************************
var (
info Info
infoMutex sync.RWMutex
)
// Info holds the details for the MySQL connection.
type Info struct {
Username string
Password string
Database string
Charset string
Collation string
Hostname string
Port int
Parameter string
MigrationFolder string
Extension string
}
// SetConfig stores the config.
func SetConfig(i Info) {
infoMutex.Lock()
info = i
infoMutex.Unlock()
}
// Config returns the config.
func Config() Info {
infoMutex.RLock()
defer infoMutex.RUnlock()
return info
}
// ResetConfig removes the config.
func ResetConfig() {
infoMutex.Lock()
info = Info{}
infoMutex.Unlock()
}
// *****************************************************************************
// Database Handling
// *****************************************************************************
// Connect to the database.
func Connect(specificDatabase bool) error {
var err error
// Connect to MySQL and ping
if SQL, err = gm.Open("mysql", dsn(specificDatabase)); err != nil {
return err
}
return err
}
// Disconnect the database connection.
func Disconnect() error {
return SQL.Close()
}
// Create a new database.
func Create() error {
// Set defaults
ci := setDefaults()
// Create the database
err := SQL.Exec(fmt.Sprintf(`CREATE DATABASE %v
DEFAULT CHARSET = %v
COLLATE = %v
;`, ci.Database,
ci.Charset,
ci.Collation)).Error
return err
}
// Drop a database.
func Drop() error {
// Drop the database
err := SQL.Exec(fmt.Sprintf(`DROP DATABASE %v;`, Config().Database)).Error
return err
}
// *****************************************************************************
// MySQL Specific
// *****************************************************************************
var (
// SQL wrapper
SQL *gm.DB
)
// DSN returns the Data Source Name.
func dsn(includeDatabase bool) string {
// Set defaults
ci := setDefaults()
// Build parameters
param := ci.Parameter
// If parameter is specified, add a question mark
// Don't add one if a question mark is already there
if len(ci.Parameter) > 0 && !strings.HasPrefix(ci.Parameter, "?") {
param = "?" + ci.Parameter
}
// Add collation
if !strings.Contains(param, "collation") {
if len(param) > 0 {
param += "&collation=" + ci.Collation
} else {
param = "?collation=" + ci.Collation
}
}
// Add charset
if !strings.Contains(param, "charset") {
if len(param) > 0 {
param += "&charset=" + ci.Charset
} else {
param = "?charset=" + ci.Charset
}
}
// Example: root:password@tcp(localhost:3306)/test
s := fmt.Sprintf("%v:%v@tcp(%v:%d)/%v", ci.Username, ci.Password, ci.Hostname, ci.Port, param)
if includeDatabase {
s = fmt.Sprintf("%v:%v@tcp(%v:%d)/%v%v", ci.Username, ci.Password, ci.Hostname, ci.Port, ci.Database, param)
}
return s
}
// setDefaults sets the charset and collation if they are not set.
func setDefaults() Info {
ci := Config()
if len(ci.Charset) == 0 {
ci.Charset = "utf8"
}
if len(ci.Collation) == 0 {
ci.Collation = "utf8_unicode_ci"
}
return ci
}
This is an example of how to change the blue-jay/blueprint/model/user/user.go file to work with Gorm:
// Package user provides access to the user table in the MySQL database.
package user
import (
"time"
database "github.com/blue-jay/blueprint/lib/gorm"
"github.com/blue-jay/blueprint/model"
"github.com/go-sql-driver/mysql"
)
// User table.
type User struct {
ID uint32 `db:"id"`
FirstName string `db:"first_name"`
LastName string `db:"last_name"`
Email string `db:"email"`
Password string `db:"password"`
UserStatus UserStatus
StatusID uint8 `db:"status_id"`
CreatedAt mysql.NullTime `db:"created_at"`
UpdatedAt mysql.NullTime `db:"updated_at"`
DeletedAt mysql.NullTime `db:"deleted_at"`
}
// TableName for user table.
func (User) TableName() string {
return "user"
}
// UserStatus table.
type UserStatus struct {
ID uint8 `db:"id"`
Status string `db:"status"`
CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"`
DeletedAt time.Time `db:"deleted_at"`
}
// TableName for user_status table.
func (UserStatus) TableName() string {
return "user_status"
}
// ByEmail gets user information from email.
func ByEmail(email string) (User, error) {
result := User{}
return result, model.StandardError(database.SQL.Where("email = ?", email).
First(&result).Error)
}
// Create creates user.
func Create(firstName, lastName, email, password string) error {
item := &User{
FirstName: firstName,
LastName: lastName,
Email: email,
Password: password,
StatusID: 1,
}
return model.StandardError(database.SQL.Create(item).Error)
}
The other change you'd need to make is to update the blue-jay/blueprint/model/model.go file:
// Package model provides error standardization for the models.
package model
import (
"database/sql"
"errors"
"github.com/jinzhu/gorm"
)
var (
// ErrNoResult is when no results are found.
ErrNoResult = errors.New("Result not found.")
)
// StandardError returns a model defined error.
func StandardError(err error) error {
if err == sql.ErrNoRows {
return ErrNoResult
} else if err == gorm.ErrRecordNotFound {
return ErrNoResult
}
return err
}