diff --git a/app/main.go b/app/main.go index bfbada5..4be2eed 100644 --- a/app/main.go +++ b/app/main.go @@ -121,6 +121,25 @@ func doGet(db *gorm.DB) { fmt.Printf(">> %+v %s (alive %t)\n", cert.Id, cert.CreatedAt, cert.Alive) } +func doSave(db *gorm.DB) { + repo := repository.RepoBase[models.Company]{} + repo.Init(db, nil) + + company := models.Company{ + Name: "Test company", + Address: "Some address", + City: "Some city", + Email: "email@example.org", + Oib: "123456", + } + + _, err := repo.Save(&company) + if err != nil { + panic(err) + } + fmt.Printf("New company id: %s\n", company.Id.String()) +} + func doExists(db *gorm.DB) { repo := repository.RepoBase[models.Cert]{} repo.Init(db, nil) @@ -147,7 +166,8 @@ func main() { // doMagic(db) // doList(db) - doCount(db) + // doCount(db) + doSave(db) // doGet(db) // doExists(db) // inheritance.DoInheritanceTest() diff --git a/app/models/company.go b/app/models/company.go index e4bc818..75421e0 100644 --- a/app/models/company.go +++ b/app/models/company.go @@ -21,7 +21,7 @@ type Company struct { UpdatedAt time.Time `faker:"-"` } -func (m *Company) TableName() string { +func (m Company) TableName() string { return "companies" } diff --git a/app/repository/method_list_test.go b/app/repository/method_list_test.go index e4e3b6f..52a4c32 100644 --- a/app/repository/method_list_test.go +++ b/app/repository/method_list_test.go @@ -33,9 +33,9 @@ func NewMockDB() (*sql.DB, *gorm.DB, sqlmock.Sqlmock) { } type MyModel struct { - Id uuid.UUID + Id *uuid.UUID `gorm:"type(uuid);unique"` Value string - Count int + Cnt int } func (m MyModel) TableName() string { @@ -46,7 +46,7 @@ type MyModelFilter struct { Id *uuid.UUID `filterfield:"field=id,operator=EQ"` Ids *[]uuid.UUID `filterfield:"field=id,operator=IN"` Value *string `filterfield:"field=value,operator=EQ"` - Count *int `filterfield:"field=count,operator=GT"` + Cnt *int `filterfield:"field=cnt,operator=GT"` } func TestListMethod(t *testing.T) { @@ -65,13 +65,13 @@ func TestListMethod(t *testing.T) { Direction: OrderASC, }, { - Field: "count", + Field: "cnt", Direction: OrderDESC, }, }, } - sql := "SELECT * FROM my_models ORDER BY id,count DESC" + sql := "SELECT * FROM my_models ORDER BY id,cnt DESC" mock.ExpectQuery(fmt.Sprintf("^%s$", regexp.QuoteMeta(sql))) _, err := repo.List(filter, &options) @@ -198,10 +198,10 @@ func TestListMethod(t *testing.T) { filter := MyModelFilter{ Id: &id, Value: &value, - Count: &count, + Cnt: &count, } - sql := "SELECT * FROM my_models WHERE my_models.id = $1 AND my_models.value = $2 AND my_models.count > $3" + sql := "SELECT * FROM my_models WHERE my_models.id = $1 AND my_models.value = $2 AND my_models.cnt > $3" mock.ExpectQuery(fmt.Sprintf("^%s$", regexp.QuoteMeta(sql))). WithArgs(id, value, count) @@ -226,7 +226,7 @@ func TestListMethod(t *testing.T) { filter := MyModelFilter{ Id: &id, Value: &value, - Count: &count, + Cnt: &count, } options := ListOptions{ Pagination: &Pagination{ @@ -235,7 +235,7 @@ func TestListMethod(t *testing.T) { }, } - sql := "SELECT * FROM my_models WHERE my_models.id = $1 AND my_models.value = $2 AND my_models.count > $3 LIMIT $4 OFFSET $5" + sql := "SELECT * FROM my_models WHERE my_models.id = $1 AND my_models.value = $2 AND my_models.cnt > $3 LIMIT $4 OFFSET $5" mock.ExpectQuery(fmt.Sprintf("^%s$", regexp.QuoteMeta(sql))). WithArgs(id, value, count, options.Pagination.Limit, options.Pagination.Offset) @@ -258,11 +258,11 @@ func TestListMethod(t *testing.T) { options := ListOptions{ Only: &[]string{ "id", - "count", + "cnt", }, } - sql := "SELECT id,count FROM my_models" + sql := "SELECT id,cnt FROM my_models" mock.ExpectQuery(fmt.Sprintf("^%s$", regexp.QuoteMeta(sql))) _, err := repo.List(filter, &options) diff --git a/app/repository/method_save.go b/app/repository/method_save.go new file mode 100644 index 0000000..7bd90c6 --- /dev/null +++ b/app/repository/method_save.go @@ -0,0 +1,18 @@ +package repository + +import ( + "gorm.io/gorm/schema" +) + +type SaveMethod[T schema.Tabler] struct { + repo *RepoBase[T] +} + +func (m *SaveMethod[T]) Init(repo *RepoBase[T]) { + m.repo = repo +} + +func (m SaveMethod[T]) Save(model *T) (*T, error) { + result := m.repo.dbConn.Save(model) + return model, result.Error +} diff --git a/app/repository/method_save_test.go b/app/repository/method_save_test.go new file mode 100644 index 0000000..0822945 --- /dev/null +++ b/app/repository/method_save_test.go @@ -0,0 +1,69 @@ +package repository + +import ( + "fmt" + "regexp" + "testing" + + "github.com/DATA-DOG/go-sqlmock" + "github.com/google/uuid" + "github.com/stretchr/testify/assert" +) + +func TestSaveMethod(t *testing.T) { + t.Run("Save new model", func(t *testing.T) { + sqldb, db, mock := NewMockDB() + defer sqldb.Close() + + repo := RepoBase[MyModel]{} + repo.Init(db, nil) + + model := MyModel{ + Value: "some value", + Cnt: 123, + } + + sql := "INSERT INTO my_models (id,value,cnt) VALUES ($1,$2,$3)" + mock.ExpectBegin() + mock.ExpectExec(fmt.Sprintf("^%s$", regexp.QuoteMeta(sql))). + WithArgs(model.Id, model.Value, model.Cnt). + WillReturnResult(sqlmock.NewResult(1, 1)) + mock.ExpectCommit() + + _, err := repo.Save(&model) + assert.Nil(t, err) + + if err := mock.ExpectationsWereMet(); err != nil { + t.Errorf("there were unfulfilled expectations: %s", err) + } + }) + + t.Run("Update existing model", func(t *testing.T) { + sqldb, db, mock := NewMockDB() + defer sqldb.Close() + + repo := RepoBase[MyModel]{} + repo.Init(db, nil) + + id := uuid.New() + model := MyModel{ + Id: &id, + Value: "some value", + Cnt: 123, + } + + sql := "UPDATE my_models SET value=$1,cnt=$2 WHERE id = $3" + mock.ExpectBegin() + mock.ExpectExec(fmt.Sprintf("^%s$", regexp.QuoteMeta(sql))). + WithArgs(model.Value, model.Cnt, model.Id). + WillReturnResult(sqlmock.NewResult(1, 1)) + mock.ExpectCommit() + + _, err := repo.Save(&model) + assert.Nil(t, err) + + if err := mock.ExpectationsWereMet(); err != nil { + t.Errorf("there were unfulfilled expectations: %s", err) + } + }) +} diff --git a/app/repository/repository.go b/app/repository/repository.go index bc2950b..c2ac08b 100644 --- a/app/repository/repository.go +++ b/app/repository/repository.go @@ -21,11 +21,11 @@ type RepoBase[T schema.Tabler] struct { GetMethod[T] ExistsMethod[T] CountMethod[T] - methods []MethodInitInterface[T] + SaveMethod[T] } -func (repo *RepoBase[T]) InitMethods() { - for _, method := range repo.methods { +func (repo *RepoBase[T]) InitMethods(methods []MethodInitInterface[T]) { + for _, method := range methods { method.Init(repo) } } @@ -42,11 +42,12 @@ func (m *RepoBase[T]) Init(dbConn *gorm.DB, options *RepoOptions) { } } - m.methods = []MethodInitInterface[T]{ + methods := []MethodInitInterface[T]{ &m.ListMethod, &m.GetMethod, &m.ExistsMethod, &m.CountMethod, + &m.SaveMethod, } - m.InitMethods() + m.InitMethods(methods) }