Compare commits

...

2 Commits

Author SHA1 Message Date
d328bc3fbd
fix time.Time fields not being saved
via adding a special case in the `serializeIDs` function (in document_internals.go)
2025-03-27 16:02:22 -04:00
11d31fbbc1
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
2025-03-27 00:12:19 -04:00
3 changed files with 36 additions and 12 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

@ -83,10 +83,14 @@ func serializeIDs(input interface{}) interface{} {
}
}
} else {
if fv.Type() == reflect.TypeFor[time.Time]() {
ret0[bbson.Name] = fv.Interface()
} else {
ret0[bbson.Name] = serializeIDs(fv.Interface())
}
}
}
ret = ret0
}
@ -102,7 +106,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 +122,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)