improve Save api

add a `SaveWith` function that accepts `SaveOptions` as a parameter, letting you tweak things like whether timestamps will be set before an insert or update operation
This commit is contained in:
☙◦ The Tablet ❀ GamerGirlandCo ◦❧ 2025-03-27 00:12:19 -04:00
parent bb37212be7
commit 11d31fbbc1
Signed by: tablet
GPG Key ID: 924A5F6AF051E87C
3 changed files with 31 additions and 11 deletions

View File

@ -21,6 +21,7 @@ type IDocument interface {
Delete() error
Remove() error
Save() error
SaveWith(opts *SaveOptions) error
setSelf(arg interface{})
getExists() bool
setExists(n bool)
@ -33,6 +34,10 @@ type IDocument interface {
setModel(m Model)
}
type SaveOptions struct {
SetTimestamps bool
}
func (d *Document) getCreated() time.Time {
return d.Created
}
@ -89,25 +94,33 @@ func (d *Document) Remove() error {
return d.Delete()
}
// Save - updates this Model in the database,
// or inserts it if it doesn't exist
func (d *Document) Save() error {
// SaveWith - updates this Model in the database,
// or inserts it if it doesn't exist, using the provided
// SaveOptions
func (d *Document) SaveWith(opts *SaveOptions) error {
val := valueOf(d.self)
if val.Kind() == reflect.Slice {
for i := 0; i < val.Len(); i++ {
cur := val.Index(i)
asHId := asId(cur.Interface())
if err := doSave(d.model.getColl(), !d.exists && reflect.ValueOf(asHId.Id()).IsZero(), cur.Interface()); err != nil {
if err := doSave(d.model.getColl(), !d.exists, opts, cur.Interface()); err != nil {
return err
}
}
return nil
} else {
asHId := asId(val.Interface())
return doSave(d.model.getColl(), !d.exists && reflect.ValueOf(asHId.Id()).IsZero(), d.self)
return doSave(d.model.getColl(), !d.exists, opts, d.self)
}
}
// Save - updates this Model in the database,
// or inserts it if it doesn't exist, using
// default SaveOptions
func (d *Document) Save() error {
return d.SaveWith(&SaveOptions{
SetTimestamps: true,
})
}
func (d *Document) serializeToStore() any {
return serializeIDs((d).self)
}

View File

@ -102,7 +102,7 @@ func serializeIDs(input interface{}) interface{} {
}
return ret
}
func doSave(c *mongo.Collection, isNew bool, arg interface{}) error {
func doSave(c *mongo.Collection, isNew bool, opts *SaveOptions, arg interface{}) error {
var err error
d, ok := arg.(IDocument)
if !ok {
@ -118,10 +118,12 @@ func doSave(c *mongo.Collection, isNew bool, arg interface{}) error {
}
var asHasId = vp.Interface().(HasID)
var asModel = vp.Interface().(IDocument)
if isNew {
if isNew && opts.SetTimestamps {
d.setCreated(now)
}
if opts.SetTimestamps {
d.setModified(now)
}
idxs := d.getModel().getIdxs()
for _, i := range idxs {
_, err = c.Indexes().CreateOne(context.TODO(), *i)

View File

@ -45,7 +45,12 @@ func asId(i interface{}) HasID {
var ok bool
switch v.Kind() {
case reflect.Struct:
v = reflect.New(reflect.PointerTo(v.Type()))
asHasId, ok = v.Interface().(HasID)
if ok {
return asHasId
}
v = reflect.New(v.Type())
v.Elem().Set(reflect.ValueOf(i))
fallthrough
case reflect.Pointer:
asHasId, ok = v.Interface().(HasID)