Don't do real delete when deleted_at column exist

This commit is contained in:
Jinzhu 2013-10-29 09:01:48 +08:00
parent bc785a9173
commit 7e5dc40f6f
5 changed files with 61 additions and 10 deletions

View File

@ -24,6 +24,7 @@ type Chain struct {
offsetStr string offsetStr string
limitStr string limitStr string
specifiedTableName string specifiedTableName string
unscoped bool
} }
func (s *Chain) err(err error) error { func (s *Chain) err(err error) error {
@ -47,6 +48,7 @@ func (s *Chain) do(value interface{}) *Do {
do.offsetStr = s.offsetStr do.offsetStr = s.offsetStr
do.limitStr = s.limitStr do.limitStr = s.limitStr
do.specifiedTableName = s.specifiedTableName do.specifiedTableName = s.specifiedTableName
do.unscoped = s.unscoped
s.value = value s.value = value
do.setModel(value) do.setModel(value)
@ -177,6 +179,11 @@ func (s *Chain) CreateTable(value interface{}) *Chain {
return s return s
} }
func (s *Chain) Unscoped() *Chain {
s.unscoped = true
return s
}
func (s *Chain) Table(name string) *Chain { func (s *Chain) Table(name string) *Chain {
s.specifiedTableName = name s.specifiedTableName = name
return s return s

25
do.go
View File

@ -7,6 +7,7 @@ import (
"reflect" "reflect"
"regexp" "regexp"
"strconv" "strconv"
"time"
"strings" "strings"
) )
@ -25,13 +26,13 @@ type Do struct {
sql string sql string
sqlVars []interface{} sqlVars []interface{}
whereClause []map[string]interface{} whereClause []map[string]interface{}
orClause []map[string]interface{} orClause []map[string]interface{}
selectStr string selectStr string
orderStrs []string orderStrs []string
offsetStr string offsetStr string
limitStr string limitStr string
unscoped bool
updateAttrs map[string]interface{} updateAttrs map[string]interface{}
ignoreProtectedAttrs bool ignoreProtectedAttrs bool
} }
@ -184,9 +185,15 @@ func (s *Do) prepareDeleteSql() {
func (s *Do) delete() { func (s *Do) delete() {
s.err(s.model.callMethod("BeforeDelete")) s.err(s.model.callMethod("BeforeDelete"))
s.prepareDeleteSql()
if !s.hasError() { if !s.hasError() {
s.exec() if s.model.hasColumn("DeletedAt") {
delete_sql := "deleted_at=" + s.addToVars(time.Now())
s.sql = fmt.Sprintf("UPDATE %v SET %v %v", s.tableName(), delete_sql, s.combinedSql())
s.exec()
} else {
s.prepareDeleteSql()
s.exec()
}
if !s.hasError() { if !s.hasError() {
s.err(s.model.callMethod("AfterDelete")) s.err(s.model.callMethod("AfterDelete"))
} }

View File

@ -53,7 +53,6 @@ func init() {
if err != nil { if err != nil {
fmt.Printf("Got error when try to delete table uses, %+v\n", err) fmt.Printf("Got error when try to delete table uses, %+v\n", err)
} }
db.Exec("drop table products;") db.Exec("drop table products;")
orm := db.CreateTable(&User{}) orm := db.CreateTable(&User{})
@ -691,3 +690,28 @@ func TestUpdates(t *testing.T) {
t.Errorf("We should have Product fgh") t.Errorf("We should have Product fgh")
} }
} }
func TestSoftDelete(t *testing.T) {
type Order struct {
Id int64
Amount int64
DeletedAt time.Time
}
db.Exec("drop table orders;")
db.CreateTable(&Order{})
order := Order{Amount: 1234}
db.Save(&order)
if db.Find(&Order{}, "amount = 1234").Error != nil {
t.Errorf("No errors should happen when save an order")
}
db.Delete(&order)
if db.Find(&Order{}, "amount = 1234").Error == nil {
t.Errorf("Can't find the user because it is soft deleted")
}
if db.Unscoped().Find(&Order{}, "amount = 1234").Error != nil {
t.Errorf("Should be able to find out the soft deleted user with unscoped")
}
}

View File

@ -57,6 +57,10 @@ func (s *DB) Delete(value interface{}) *Chain {
return s.buildChain().Delete(value) return s.buildChain().Delete(value)
} }
func (s *DB) Unscoped() *Chain {
return s.buildChain().Unscoped()
}
func (s *DB) Exec(sql string) *Chain { func (s *DB) Exec(sql string) *Chain {
return s.buildChain().Exec(sql) return s.buildChain().Exec(sql)
} }

View File

@ -104,6 +104,15 @@ func (m *Model) columnsAndValues(operation string) map[string]interface{} {
return results return results
} }
func (m *Model) hasColumn(name string) bool {
if m.data == nil {
return false
}
value := reflect.ValueOf(m.data).Elem().FieldByName(name)
return value.IsValid()
}
func (m *Model) tableName() (str string, err error) { func (m *Model) tableName() (str string, err error) {
if m.data == nil { if m.data == nil {
err = errors.New("Model haven't been set") err = errors.New("Model haven't been set")