Skip to content

Commit

Permalink
feat(delete): allow deletion of models (#37)
Browse files Browse the repository at this point in the history
Signed-off-by: Geoffrey Bauduin <[email protected]>
  • Loading branch information
geoffreybauduin authored Feb 12, 2020
1 parent cc7c191 commit 918c8f5
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 0 deletions.
46 changes: 46 additions & 0 deletions model.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,48 +13,84 @@ import (

// Model is the interface every model should implement from
type Model interface {
// GetDBP should return the DBProvider tied to this model
GetDBP() DBProvider
// SetDBP allows setting a DBProvider to the model, then returned by GetDBP
SetDBP(dbp DBProvider)
// Save allows saving the model
Save() error
// Load loads the model from database given the current struct
Load(dbp DBProvider) error
// Delete removes the model from database
Delete() error
// DBHookBeforeInsert is a hook called before performing a DB insertion
DBHookBeforeInsert() error
// DBHookBeforeUpdate is a hook called before performing a DB update
DBHookBeforeUpdate() error
// DBHookBeforeDelete is a hook called before performing a DB delete
DBHookBeforeDelete() error
}

// DatabaseModel is the struct every model should compose
type DatabaseModel struct {
dbp DBProvider `db:"-"`
}

// SetDBP allows setting a DBProvider to the model, then returned by GetDBP
func (dm *DatabaseModel) SetDBP(dbp DBProvider) {
dm.dbp = dbp
}

// GetDBP should return the DBProvider tied to this model
func (dm *DatabaseModel) GetDBP() DBProvider {
return dm.dbp
}

// Save allows saving the model
// In order to be usable, this function needs to be redfined by each
// composition of this structure
func (dm *DatabaseModel) Save() error {
return errors.NotImplementedf("Save")
}

// Load loads the model from database given the current struct
// In order to be usable, this function needs to be redfined by each
// composition of this structure
func (dm *DatabaseModel) Load(dbp DBProvider) error {
return errors.NotImplementedf("Load")
}

// Delete removes the model from database
// In order to be usable, this function needs to be redfined by each
// composition of this structure
func (dm *DatabaseModel) Delete() error {
return errors.NotImplementedf("Delete")
}

// DBHookBeforeInsert is a hook called before performing a DB insertion
// By default, this function does not do anything. If needed, you will have
// to implement this function in your structure composing this one
// in order to have your code hook executed
func (dm *DatabaseModel) DBHookBeforeInsert() error {
return nil
}

// DBHookBeforeUpdate is a hook called before performing a DB update
// By default, this function does not do anything. If needed, you will have
// to implement this function in your structure composing this one
// in order to have your code hook executed
func (dm *DatabaseModel) DBHookBeforeUpdate() error {
return nil
}

// DBHookBeforeDelete is a hook called before performing a DB delete
// By default, this function does not do anything. If needed, you will have
// to implement this function in your structure composing this one
// in order to have your code hook executed
func (dm *DatabaseModel) DBHookBeforeDelete() error {
return nil
}

type cnt struct {
Count uint64 `db:"count"`
}
Expand Down Expand Up @@ -472,3 +508,13 @@ func getFieldInModel(m Model, tag, equals string) (int, string) {
}
return -1, ""
}

// GenericDelete will delete the provided model from its database
// Returns the number of rows deleted
func GenericDelete(m Model) (int64, error) {
err := m.DBHookBeforeDelete()
if err != nil {
return 0, err
}
return m.GetDBP().DB().Delete(m)
}
55 changes: 55 additions & 0 deletions model_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -485,3 +485,58 @@ func TestSubqueryloadWithInvalidTypeReturned(t *testing.T) {
assert.Error(t, err)
assert.Contains(t, err.Error(), "a subquery returned a non-array and non-slice type 'ptr', which is not handled")
}

func TestGenericDelete(t *testing.T) {
killDb, err := testdata.SetupTestDatabase("test")
defer killDb()
assert.NoError(t, err)
dbp, err := yaorm.NewDBProvider(context.TODO(), "test")
assert.NoError(t, err)
category := &testdata.Category{Name: "category"}
saveModel(t, dbp, category)
category2 := &testdata.Category{Name: "category"}
saveModel(t, dbp, category2)
rows, errDelete := yaorm.GenericDelete(category)
assert.NoError(t, errDelete)
assert.Equal(t, int64(1), rows)
rows, errDelete = yaorm.GenericDelete(category)
assert.NoError(t, errDelete)
assert.Equal(t, int64(0), rows)
notFound, err := yaorm.GenericSelectOne(dbp, testdata.NewCategoryFilter().ID(yaormfilter.Equals(category.ID)))
assert.Error(t, err)
assert.Nil(t, notFound)
assert.True(t, errors.IsNotFound(err))
found, err := yaorm.GenericSelectOne(dbp, testdata.NewCategoryFilter().ID(yaormfilter.Equals(category2.ID)))
assert.NoError(t, err)
assert.NotNil(t, found)
}

func TestGenericDelete_MultiplePrimaryKeys(t *testing.T) {
killDb, err := testdata.SetupTestDatabase("test")
defer killDb()
assert.NoError(t, err)
dbp, err := yaorm.NewDBProvider(context.TODO(), "test")
assert.NoError(t, err)
category := &testdata.Category{Name: "category"}
saveModel(t, dbp, category)
post := &testdata.Post{Subject: "subject", CategoryID: category.ID}
saveModel(t, dbp, post)
tag := &testdata.Tag{Tag: "tag"}
saveModel(t, dbp, tag)
tag2 := &testdata.Tag{Tag: "tag2"}
saveModel(t, dbp, tag2)
posttag := &testdata.PostTag{TagID: tag.ID, PostID: post.ID}
saveModel(t, dbp, posttag)
posttag2 := &testdata.PostTag{TagID: tag2.ID, PostID: post.ID}
saveModel(t, dbp, posttag2)
rows, err := yaorm.GenericDelete(posttag)
assert.NoError(t, err)
assert.Equal(t, int64(1), rows)
rows, err = yaorm.GenericDelete(posttag)
assert.NoError(t, err)
assert.Equal(t, int64(0), rows)
listTags, err := yaorm.GenericSelectAll(dbp, testdata.NewPostTagFilter().PostID(yaormfilter.Equals(post.ID)))
assert.NoError(t, err)
assert.Len(t, listTags, 1)
assert.Equal(t, tag2.ID, listTags[0].(*testdata.PostTag).TagID)
}

0 comments on commit 918c8f5

Please sign in to comment.