Skip to content

Commit 764ca5d

Browse files
authored
feat(gorm/scope): Added scope method (#118)
* feat(gorm/scope): Added scope method Signed-off-by: Flc゛ <[email protected]> * feat(gorm/scope): Added scope method Signed-off-by: Flc゛ <[email protected]> * feat(gorm/scope): Added scope method Signed-off-by: Flc゛ <[email protected]> * feat(gorm/scope): Added scope method Signed-off-by: Flc゛ <[email protected]> * feat(gorm/scope): Added scope method Signed-off-by: Flc゛ <[email protected]> * feat(gorm/scope): Added scope method Signed-off-by: Flc゛ <[email protected]> * feat(gorm/scope): Added scope method Signed-off-by: Flc゛ <[email protected]> * feat(gorm/scope): Added scope method Signed-off-by: Flc゛ <[email protected]> * feat(gorm/scope): Added scope method Signed-off-by: Flc゛ <[email protected]> * feat(gorm/scope): Added scope method Signed-off-by: Flc゛ <[email protected]> * feat(gorm/scope): Added scope method Signed-off-by: Flc゛ <[email protected]> * feat(gorm/scope): Added `OrderBy` scope method Signed-off-by: Flc゛ <[email protected]> * feat(gorm/scope): Added scope method Signed-off-by: Flc゛ <[email protected]> * feat(gorm/scope): Added scope method Signed-off-by: Flc゛ <[email protected]> * feat(gorm/scope): Added scope method Signed-off-by: Flc゛ <[email protected]> * feat(gorm/scope): Added scope method Signed-off-by: Flc゛ <[email protected]> --------- Signed-off-by: Flc゛ <[email protected]>
1 parent 9d4b24a commit 764ca5d

16 files changed

+1286
-0
lines changed

.github/workflows/test.yml

+16
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ jobs:
1414
matrix:
1515
go-version: [ 1.18.x, 1.19.x, 1.20.x, 1.21.x, 1.22.x ]
1616
platform: [ ubuntu-latest ]
17+
mysql-version: ['mysql:latest', 'mysql:5.7']
1718
runs-on: ${{ matrix.platform }}
1819

1920
services:
@@ -23,6 +24,21 @@ jobs:
2324
--health-cmd "redis-cli ping" --health-interval 10s --health-timeout 5s --health-retries 5
2425
ports:
2526
- 6379:6379
27+
mysql:
28+
image: ${{ matrix.mysql-version }}
29+
env:
30+
MYSQL_DATABASE: gorm
31+
MYSQL_USER: gorm
32+
MYSQL_PASSWORD: gorm
33+
MYSQL_RANDOM_ROOT_PASSWORD: "yes"
34+
ports:
35+
- 3306:3306
36+
options: >-
37+
--health-cmd "mysqladmin ping -ugorm -pgorm"
38+
--health-interval 10s
39+
--health-start-period 10s
40+
--health-timeout 5s
41+
--health-retries 10
2642
2743
steps:
2844
- name: Checkout code

go.mod

+4
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ require (
1414
github.com/stretchr/testify v1.8.4
1515
golang.org/x/term v0.17.0
1616
golang.org/x/text v0.14.0
17+
gorm.io/driver/mysql v1.5.4
1718
gorm.io/gorm v1.25.7
1819
)
1920

@@ -31,9 +32,12 @@ require (
3132
github.com/go-playground/locales v0.14.1 // indirect
3233
github.com/go-playground/universal-translator v0.18.1 // indirect
3334
github.com/go-playground/validator/v10 v10.18.0 // indirect
35+
github.com/go-sql-driver/mysql v1.7.0 // indirect
3436
github.com/goccy/go-json v0.10.2 // indirect
3537
github.com/golang/protobuf v1.5.3 // indirect
3638
github.com/gorilla/mux v1.8.1 // indirect
39+
github.com/jinzhu/inflection v1.0.0 // indirect
40+
github.com/jinzhu/now v1.1.5 // indirect
3741
github.com/json-iterator/go v1.1.12 // indirect
3842
github.com/klauspost/cpuid/v2 v2.2.6 // indirect
3943
github.com/kr/text v0.2.0 // indirect

go.sum

+8
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn
4545
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
4646
github.com/go-playground/validator/v10 v10.18.0 h1:BvolUXjp4zuvkZ5YN5t7ebzbhlUtPsPm2S9NAZ5nl9U=
4747
github.com/go-playground/validator/v10 v10.18.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
48+
github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
49+
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
4850
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
4951
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
5052
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
@@ -57,7 +59,10 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
5759
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
5860
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
5961
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
62+
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
63+
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
6064
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
65+
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
6166
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
6267
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
6368
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
@@ -141,6 +146,9 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN
141146
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
142147
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
143148
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
149+
gorm.io/driver/mysql v1.5.4 h1:igQmHfKcbaTVyAIHNhhB888vvxh8EdQ2uSUT0LPcBso=
150+
gorm.io/driver/mysql v1.5.4/go.mod h1:9rYxJph/u9SWkWc9yY4XJ1F/+xO0S/ChOmbk3+Z5Tvs=
151+
gorm.io/gorm v1.25.7-0.20240204074919-46816ad31dde/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
144152
gorm.io/gorm v1.25.7 h1:VsD6acwRjz2zFxGO50gPO6AkNs7KKnvfzUjHQhZDz/A=
145153
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
146154
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=

gorm/scopes/README.md

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Gorm/Scopes
2+
3+
## Example
4+
5+
```go
6+
package main
7+
8+
import (
9+
"time"
10+
11+
"gorm.io/gorm"
12+
13+
"github.com/go-kratos-ecosystem/components/v2/gorm/scopes"
14+
)
15+
16+
func main() {
17+
var db *gorm.DB
18+
19+
db.Scopes(scopes.
20+
// trait
21+
When(true, func(db *gorm.DB) *gorm.DB {
22+
return db.Where("deleted_at IS NULL")
23+
}).
24+
Unless(true, func(db *gorm.DB) *gorm.DB {
25+
return db.Where("deleted_at IS NOT NULL")
26+
}).
27+
28+
// Where
29+
Where("name = ?", "Flc").
30+
WhereBetween("created_at", time.Now(), time.Now()).
31+
WhereNotBetween("created_at", time.Now(), time.Now()).
32+
WhereIn("name", "Flc", "Flc 2").
33+
WhereNotIn("name", "Flc", "Flc 2").
34+
WhereLike("name", "Flc%").
35+
WhereNotLike("name", "Flc%").
36+
WhereEq("name", "Flc").
37+
WhereNe("name", "Flc").
38+
WhereGt("age", 18).
39+
WhereEgt("age", 18).
40+
WhereLt("age", 18).
41+
WhereElt("age", 18).
42+
43+
// Order
44+
OrderBy("id").
45+
OrderBy("id", "desc").
46+
OrderBy("id", "asc").
47+
OrderByDesc("id").
48+
OrderByAsc("id").
49+
OrderByRaw("id desc").
50+
51+
// Limit
52+
Limit(10).
53+
Take(10).
54+
55+
// Offset
56+
Offset(10).
57+
Skip(10).
58+
59+
// Page
60+
Page(1, 20).
61+
62+
// To Scope()
63+
Scope()).
64+
Find(&[]struct{}{})
65+
}
66+
```

gorm/scopes/init_test.go

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package scopes
2+
3+
import (
4+
"log"
5+
"os"
6+
"time"
7+
8+
"gorm.io/driver/mysql"
9+
"gorm.io/gorm"
10+
)
11+
12+
var (
13+
DB *gorm.DB
14+
dsn = "gorm:gorm@tcp(localhost:3306)/gorm?charset=utf8&parseTime=True&loc=Local"
15+
)
16+
17+
type User struct {
18+
gorm.Model
19+
Name string `gorm:"column:name"`
20+
Age uint `gorm:"column:age"`
21+
Sex string `gorm:"column:sex"`
22+
Birthday *time.Time `gorm:"column:birthday"`
23+
Address *string `gorm:"column:address"`
24+
}
25+
26+
func init() {
27+
var err error
28+
DB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
29+
if err != nil {
30+
log.Println("failed to connect database, got error", err)
31+
os.Exit(1)
32+
}
33+
34+
runMigrations()
35+
}
36+
37+
func runMigrations() {
38+
var err error
39+
models := []interface{}{&User{}}
40+
41+
if err = DB.Migrator().DropTable(models...); err != nil {
42+
log.Printf("Didn't drop table, got error %v\n", err)
43+
os.Exit(1)
44+
}
45+
46+
if err = DB.AutoMigrate(models...); err != nil {
47+
log.Printf("Failed to auto migrate, but got error %v\n", err)
48+
os.Exit(1)
49+
}
50+
51+
for _, m := range models {
52+
if !DB.Migrator().HasTable(m) {
53+
log.Printf("Didn't create table for %#v\n", m)
54+
os.Exit(1)
55+
}
56+
}
57+
}
58+
59+
type GetUserOptions struct {
60+
Age int
61+
Birthday *time.Time
62+
Address *string
63+
}
64+
65+
func GetUser(name string, opts GetUserOptions) *User {
66+
var (
67+
birthday = time.Now().Round(time.Second)
68+
user = User{
69+
Name: name,
70+
Age: 18,
71+
Birthday: &birthday,
72+
}
73+
)
74+
75+
if opts.Age > 0 {
76+
user.Age = uint(opts.Age)
77+
}
78+
79+
if opts.Birthday != nil {
80+
user.Birthday = opts.Birthday
81+
}
82+
83+
if opts.Address != nil {
84+
user.Address = opts.Address
85+
}
86+
87+
return &user
88+
}
89+
90+
func CleanUsers() {
91+
DB.Session(&gorm.Session{AllowGlobalUpdate: true}).Delete(&User{})
92+
}

gorm/scopes/order.go

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package scopes
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
7+
"gorm.io/gorm"
8+
)
9+
10+
// OrderBy add order by condition
11+
//
12+
// OrderBy("name")
13+
// OrderBy("name", "desc")
14+
// OrderBy("name", "asc")
15+
func OrderBy(column string, reorder ...string) *Scopes {
16+
return New().OrderBy(column, reorder...)
17+
}
18+
19+
// OrderByDesc add order by desc condition
20+
//
21+
// OrderByDesc("name")
22+
func OrderByDesc(column string) *Scopes {
23+
return New().OrderByDesc(column)
24+
}
25+
26+
// OrderByAsc add order by asc condition
27+
//
28+
// OrderByAsc("name")
29+
func OrderByAsc(column string) *Scopes {
30+
return New().OrderByAsc(column)
31+
}
32+
33+
// OrderByRaw add order by raw condition
34+
//
35+
// OrderByRaw("name desc")
36+
// OrderByRaw("name asc")
37+
// OrderByRaw("name desc, age asc")
38+
// OrderByRaw("FIELD(id, 3, 1, 2)")
39+
func OrderByRaw(sql interface{}) *Scopes {
40+
return New().OrderByRaw(sql)
41+
}
42+
43+
// OrderBy add order by condition
44+
//
45+
// OrderBy("name")
46+
// OrderBy("name", "desc")
47+
// OrderBy("name", "asc")
48+
func (s *Scopes) OrderBy(column string, reorder ...string) *Scopes {
49+
return s.Add(func(db *gorm.DB) *gorm.DB {
50+
return db.Order(fmt.Sprintf("%s %s", column, s.buildReorder(reorder...)))
51+
})
52+
}
53+
54+
// OrderByDesc add order by desc condition
55+
//
56+
// OrderByDesc("name")
57+
func (s *Scopes) OrderByDesc(column string) *Scopes {
58+
return s.OrderBy(column, "desc")
59+
}
60+
61+
// OrderByAsc add order by asc condition
62+
//
63+
// OrderByAsc("name")
64+
func (s *Scopes) OrderByAsc(column string) *Scopes {
65+
return s.OrderBy(column, "asc")
66+
}
67+
68+
// OrderByRaw add order by raw condition
69+
//
70+
// OrderByRaw("name desc")
71+
// OrderByRaw("name asc")
72+
// OrderByRaw("name desc, age asc")
73+
// OrderByRaw("FIELD(id, 3, 1, 2)")
74+
func (s *Scopes) OrderByRaw(sql interface{}) *Scopes {
75+
return s.Add(func(db *gorm.DB) *gorm.DB {
76+
return db.Order(sql)
77+
})
78+
}
79+
80+
func (s *Scopes) buildReorder(reorder ...string) string {
81+
if len(reorder) > 0 && strings.ToUpper(reorder[0]) == "DESC" {
82+
return "DESC"
83+
}
84+
return "ASC"
85+
}

0 commit comments

Comments
 (0)