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

Add some new methods to Orm #68

Merged
merged 2 commits into from
Mar 11, 2023
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
6 changes: 2 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,11 @@ Welcome to star, PR and issues!
- [x] Mail
- [x] Validation
- [x] Mock
- [x] Hash
- [x] Crypt

## Roadmap

- [ ] Hash
- [ ] Crypt
- [ ] Broadcasting
- [ ] Delay Queue
- [ ] Queue supports DB driver
- [ ] Notifications
- [ ] Optimize unit tests
Expand Down
6 changes: 2 additions & 4 deletions README_zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,11 @@ Laravel!
- [x] 邮件
- [x] 表单验证
- [x] Mock
- [x] Hash
- [x] Crypt

## 路线图

- [ ] Hash
- [ ] Crypt
- [ ] 广播系统
- [ ] 延迟队列
- [ ] 队列支持 DB 驱动
- [ ] 消息通知
- [ ] 完善单元测试
Expand Down
56 changes: 49 additions & 7 deletions contracts/database/mocks/Query.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion contracts/database/orm.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ type Query interface {
Find(dest any, conds ...any) error
First(dest any) error
FirstOrCreate(dest any, conds ...any) error
FirstOr(dest any, callback func() error) error
FirstOrFail(dest any) error
FirstOrNew(dest any, attributes any, values ...any) error
ForceDelete(value any, conds ...any) (*Result, error)
Get(dest any) error
Group(name string) Query
Expand All @@ -57,7 +60,7 @@ type Query interface {
Table(name string, args ...any) Query
Update(column string, value any) error
Updates(values any) (*Result, error)
UpdateOrCreate(dest any, attributes any, values ...any) error
UpdateOrCreate(dest any, attributes any, values any) error
Where(query any, args ...any) Query
WithTrashed() Query
With(query string, args ...any) Query
Expand Down
34 changes: 28 additions & 6 deletions database/gorm/gorm.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,32 @@ func (r *Query) First(dest any) error {
return err
}

func (r *Query) FirstOr(dest any, callback func() error) error {
err := r.instance.First(dest).Error
if errors.Is(err, gorm.ErrRecordNotFound) {
return callback()
}

return nil
}

func (r *Query) FirstOrFail(dest any) error {
err := r.instance.First(dest).Error
if errors.Is(err, gorm.ErrRecordNotFound) {
return orm.ErrRecordNotFound
}

return err
}

func (r *Query) FirstOrNew(dest any, attributes any, values ...any) error {
if len(values) > 0 {
return r.instance.Attrs(values[0]).FirstOrInit(dest, attributes).Error
} else {
return r.instance.FirstOrInit(dest, attributes).Error
}
}

func (r *Query) FirstOrCreate(dest any, conds ...any) error {
var err error
if len(conds) > 1 {
Expand Down Expand Up @@ -527,12 +553,8 @@ func (r *Query) Updates(values any) (*contractsdatabase.Result, error) {
}, result.Error
}

func (r *Query) UpdateOrCreate(dest any, attributes any, values ...any) error {
if len(values) > 0 {
return r.instance.Assign(values[0]).FirstOrCreate(dest, attributes).Error
} else {
return r.instance.FirstOrCreate(dest, attributes).Error
}
func (r *Query) UpdateOrCreate(dest any, attributes any, values any) error {
return r.instance.Assign(values).FirstOrCreate(dest, attributes).Error
}

func (r *Query) Where(query any, args ...any) contractsdatabase.Query {
Expand Down
66 changes: 53 additions & 13 deletions database/gorm/gorm_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package gorm

import (
"errors"
"fmt"
"log"
"strconv"
Expand Down Expand Up @@ -596,7 +597,7 @@ func (s *GormQueryTestSuite) TestFirst() {
s.True(user.ID > 0)

var user1 User
s.Nil(query.Where("name = ?", "first_user").First(&user1))
s.Nil(query.Where("name", "first_user").First(&user1))
s.True(user1.ID > 0)
})
}
Expand All @@ -606,17 +607,66 @@ func (s *GormQueryTestSuite) TestFirstOrCreate() {
for driver, query := range s.queries {
s.Run(driver.String(), func() {
var user User
s.Nil(query.Where("avatar = ?", "first_or_create_avatar").FirstOrCreate(&user, User{Name: "first_or_create_user"}))
s.Nil(query.Where("avatar", "first_or_create_avatar").FirstOrCreate(&user, User{Name: "first_or_create_user"}))
s.True(user.ID > 0)

var user1 User
s.Nil(query.Where("avatar = ?", "first_or_create_avatar").FirstOrCreate(&user1, User{Name: "user"}, User{Avatar: "first_or_create_avatar1"}))
s.Nil(query.Where("avatar", "first_or_create_avatar").FirstOrCreate(&user1, User{Name: "user"}, User{Avatar: "first_or_create_avatar1"}))
s.True(user1.ID > 0)
s.True(user1.Avatar == "first_or_create_avatar1")
})
}
}

func (s *GormQueryTestSuite) TestFirstOr() {
for driver, query := range s.queries {
s.Run(driver.String(), func() {
var user User
s.Nil(query.Where("name", "first_or_user").FirstOr(&user, func() error {
user.Name = "goravel"

return nil
}))
s.Equal(uint(0), user.ID)
s.Equal("goravel", user.Name)

var user1 User
s.EqualError(query.Where("name", "first_or_user").FirstOr(&user1, func() error {
return errors.New("error")
}), "error")
s.Equal(uint(0), user1.ID)
})
}
}

func (s *GormQueryTestSuite) TestFirstOrFail() {
for driver, query := range s.queries {
s.Run(driver.String(), func() {
var user User
s.Equal(orm.ErrRecordNotFound, query.Where("name", "first_or_fail_user").FirstOrFail(&user))
s.Equal(uint(0), user.ID)
})
}
}

func (s *GormQueryTestSuite) TestFirstOrNew() {
for driver, query := range s.queries {
s.Run(driver.String(), func() {
var user User
s.Nil(query.FirstOrNew(&user, User{Name: "first_or_new_name"}))
s.Equal(uint(0), user.ID)
s.Equal("first_or_new_name", user.Name)
s.Equal("", user.Avatar)

var user1 User
s.Nil(query.FirstOrNew(&user1, User{Name: "first_or_new_name"}, User{Avatar: "first_or_new_avatar"}))
s.Equal(uint(0), user1.ID)
s.Equal("first_or_new_name", user1.Name)
s.Equal("first_or_new_avatar", user1.Avatar)
})
}
}

func (s *GormQueryTestSuite) TestGet() {
for driver, query := range s.queries {
s.Run(driver.String(), func() {
Expand Down Expand Up @@ -1279,16 +1329,6 @@ func (s *GormQueryTestSuite) TestUpdateOrCreate() {
var count int64
err = query.Model(User{}).Where("name", "update_or_create_user").Count(&count)
s.Equal(int64(1), count)

var user4 User
err = query.UpdateOrCreate(&user4, User{Name: "update_or_create_user1", Avatar: "update_or_create_avatar"})
s.Nil(err)
s.True(user4.ID > 0)

var user5 User
err = query.Where("name", "update_or_create_user1").Where("avatar", "update_or_create_avatar").Find(&user5)
s.Nil(err)
s.True(user1.ID > 0)
})
}
}
Expand Down
3 changes: 3 additions & 0 deletions database/orm/model.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package orm

import (
"errors"
"time"

"gorm.io/gorm"
Expand All @@ -9,6 +10,8 @@ import (

const Associations = clause.Associations

var ErrRecordNotFound = errors.New("record not found")

type Model struct {
ID uint `gorm:"primaryKey"`
Timestamps
Expand Down