Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(gorm/scope): Added scope method #118

Merged
merged 16 commits into from
Feb 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ jobs:
matrix:
go-version: [ 1.18.x, 1.19.x, 1.20.x, 1.21.x, 1.22.x ]
platform: [ ubuntu-latest ]
mysql-version: ['mysql:latest', 'mysql:5.7']
runs-on: ${{ matrix.platform }}

services:
Expand All @@ -23,6 +24,21 @@ jobs:
--health-cmd "redis-cli ping" --health-interval 10s --health-timeout 5s --health-retries 5
ports:
- 6379:6379
mysql:
image: ${{ matrix.mysql-version }}
env:
MYSQL_DATABASE: gorm
MYSQL_USER: gorm
MYSQL_PASSWORD: gorm
MYSQL_RANDOM_ROOT_PASSWORD: "yes"
ports:
- 3306:3306
options: >-
--health-cmd "mysqladmin ping -ugorm -pgorm"
--health-interval 10s
--health-start-period 10s
--health-timeout 5s
--health-retries 10

steps:
- name: Checkout code
Expand Down
4 changes: 4 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ require (
github.com/stretchr/testify v1.8.4
golang.org/x/term v0.17.0
golang.org/x/text v0.14.0
gorm.io/driver/mysql v1.5.4
gorm.io/gorm v1.25.7
)

Expand All @@ -31,9 +32,12 @@ require (
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.18.0 // indirect
github.com/go-sql-driver/mysql v1.7.0 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/gorilla/mux v1.8.1 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.2.6 // indirect
github.com/kr/text v0.2.0 // indirect
Expand Down
8 changes: 8 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.18.0 h1:BvolUXjp4zuvkZ5YN5t7ebzbhlUtPsPm2S9NAZ5nl9U=
github.com/go-playground/validator/v10 v10.18.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
Expand All @@ -57,7 +59,10 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
Expand Down Expand Up @@ -141,6 +146,9 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/mysql v1.5.4 h1:igQmHfKcbaTVyAIHNhhB888vvxh8EdQ2uSUT0LPcBso=
gorm.io/driver/mysql v1.5.4/go.mod h1:9rYxJph/u9SWkWc9yY4XJ1F/+xO0S/ChOmbk3+Z5Tvs=
gorm.io/gorm v1.25.7-0.20240204074919-46816ad31dde/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
gorm.io/gorm v1.25.7 h1:VsD6acwRjz2zFxGO50gPO6AkNs7KKnvfzUjHQhZDz/A=
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
Expand Down
66 changes: 66 additions & 0 deletions gorm/scopes/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Gorm/Scopes

## Example

```go
package main

import (
"time"

"gorm.io/gorm"

"github.com/go-kratos-ecosystem/components/v2/gorm/scopes"
)

func main() {
var db *gorm.DB

db.Scopes(scopes.
// trait
When(true, func(db *gorm.DB) *gorm.DB {
return db.Where("deleted_at IS NULL")
}).
Unless(true, func(db *gorm.DB) *gorm.DB {
return db.Where("deleted_at IS NOT NULL")
}).

// Where
Where("name = ?", "Flc").
WhereBetween("created_at", time.Now(), time.Now()).
WhereNotBetween("created_at", time.Now(), time.Now()).
WhereIn("name", "Flc", "Flc 2").
WhereNotIn("name", "Flc", "Flc 2").
WhereLike("name", "Flc%").
WhereNotLike("name", "Flc%").
WhereEq("name", "Flc").
WhereNe("name", "Flc").
WhereGt("age", 18).
WhereEgt("age", 18).
WhereLt("age", 18).
WhereElt("age", 18).

// Order
OrderBy("id").
OrderBy("id", "desc").
OrderBy("id", "asc").
OrderByDesc("id").
OrderByAsc("id").
OrderByRaw("id desc").

// Limit
Limit(10).
Take(10).

// Offset
Offset(10).
Skip(10).

// Page
Page(1, 20).

// To Scope()
Scope()).
Find(&[]struct{}{})
}
```
92 changes: 92 additions & 0 deletions gorm/scopes/init_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package scopes

import (
"log"
"os"
"time"

"gorm.io/driver/mysql"
"gorm.io/gorm"
)

var (
DB *gorm.DB
dsn = "gorm:gorm@tcp(localhost:3306)/gorm?charset=utf8&parseTime=True&loc=Local"
)

type User struct {
gorm.Model
Name string `gorm:"column:name"`
Age uint `gorm:"column:age"`
Sex string `gorm:"column:sex"`
Birthday *time.Time `gorm:"column:birthday"`
Address *string `gorm:"column:address"`
}

func init() {
var err error
DB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
log.Println("failed to connect database, got error", err)
os.Exit(1)
}

runMigrations()
}

func runMigrations() {
var err error
models := []interface{}{&User{}}

if err = DB.Migrator().DropTable(models...); err != nil {
log.Printf("Didn't drop table, got error %v\n", err)
os.Exit(1)
}

if err = DB.AutoMigrate(models...); err != nil {
log.Printf("Failed to auto migrate, but got error %v\n", err)
os.Exit(1)
}

for _, m := range models {
if !DB.Migrator().HasTable(m) {
log.Printf("Didn't create table for %#v\n", m)
os.Exit(1)
}
}
}

type GetUserOptions struct {
Age int
Birthday *time.Time
Address *string
}

func GetUser(name string, opts GetUserOptions) *User {
var (
birthday = time.Now().Round(time.Second)
user = User{
Name: name,
Age: 18,
Birthday: &birthday,
}
)

if opts.Age > 0 {
user.Age = uint(opts.Age)
}

if opts.Birthday != nil {
user.Birthday = opts.Birthday
}

if opts.Address != nil {
user.Address = opts.Address
}

return &user
}

func CleanUsers() {
DB.Session(&gorm.Session{AllowGlobalUpdate: true}).Delete(&User{})
}
85 changes: 85 additions & 0 deletions gorm/scopes/order.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package scopes

import (
"fmt"
"strings"

"gorm.io/gorm"
)

// OrderBy add order by condition
//
// OrderBy("name")
// OrderBy("name", "desc")
// OrderBy("name", "asc")
func OrderBy(column string, reorder ...string) *Scopes {
return New().OrderBy(column, reorder...)
}

// OrderByDesc add order by desc condition
//
// OrderByDesc("name")
func OrderByDesc(column string) *Scopes {
return New().OrderByDesc(column)
}

// OrderByAsc add order by asc condition
//
// OrderByAsc("name")
func OrderByAsc(column string) *Scopes {
return New().OrderByAsc(column)
}

// OrderByRaw add order by raw condition
//
// OrderByRaw("name desc")
// OrderByRaw("name asc")
// OrderByRaw("name desc, age asc")
// OrderByRaw("FIELD(id, 3, 1, 2)")
func OrderByRaw(sql interface{}) *Scopes {
return New().OrderByRaw(sql)
}

// OrderBy add order by condition
//
// OrderBy("name")
// OrderBy("name", "desc")
// OrderBy("name", "asc")
func (s *Scopes) OrderBy(column string, reorder ...string) *Scopes {
return s.Add(func(db *gorm.DB) *gorm.DB {
return db.Order(fmt.Sprintf("%s %s", column, s.buildReorder(reorder...)))
})
}

// OrderByDesc add order by desc condition
//
// OrderByDesc("name")
func (s *Scopes) OrderByDesc(column string) *Scopes {
return s.OrderBy(column, "desc")
}

// OrderByAsc add order by asc condition
//
// OrderByAsc("name")
func (s *Scopes) OrderByAsc(column string) *Scopes {
return s.OrderBy(column, "asc")
}

// OrderByRaw add order by raw condition
//
// OrderByRaw("name desc")
// OrderByRaw("name asc")
// OrderByRaw("name desc, age asc")
// OrderByRaw("FIELD(id, 3, 1, 2)")
func (s *Scopes) OrderByRaw(sql interface{}) *Scopes {
return s.Add(func(db *gorm.DB) *gorm.DB {
return db.Order(sql)
})
}

func (s *Scopes) buildReorder(reorder ...string) string {
if len(reorder) > 0 && strings.ToUpper(reorder[0]) == "DESC" {
return "DESC"
}
return "ASC"
}
Loading
Loading