pilagod / gorm-cursor-paginator

A paginator doing cursor-based pagination based on GORM
https://github.com/pilagod/gorm-cursor-paginator
MIT License
188 stars 44 forks source link

Allow Paginator to take in slice of pointers without Errors. #4

Closed willjleong closed 5 years ago

willjleong commented 5 years ago

Currently, if you pass the paginator Paginate()method a pointer to an slice of pointers to a struct model e.g. []*User there's an error thrown when encoding the IDs orCreatedAt to cursors and getting the reflect: call of reflect.Value.FieldByName on ptr Value.

func (p *Paginator) encode(v reflect.Value) string {
    fields := make([]string, len(p.keys))
    for index, key := range p.keys {
        fields[index] = convert(v.FieldByName(key).Interface()) // This line is failing
    }
    return encodeBase64(fields)
}

There should be a check before reflecting the gorm model to allow a slice of pointers to models to be cursor-paginated . This can be accomplished by checking to see if the key is a pointer or not and adding Indirect() when needed.

Something like this but have not tested yet:

func (p *Paginator) encode(v reflect.Value) string {
    fields := make([]string, len(p.keys))
    for index, key := range p.keys {
                 if v.Kind() == reflect.Ptr {
                         fields[index] = convert(reflect.Indirect(v).FieldByName(key).Interface()) 
                 } else {
                         fields[index] = convert(v.FieldByName(key).Interface())
                 }
    }
    return encodeBase64(fields)
}
pilagod commented 5 years ago

Thanks for your suggestion, it looks reasonable.

Would you mind sending a PR with implementation and additional test case to cover this scenario ? Or if you are not in a hurry, I can tackle this issue on the weekend : )

willjleong commented 5 years ago

@pilagod Thanks, just submitted a PR with the proposed fix and a test case testing the change/fix.

pilagod commented 5 years ago

Thanks, I have merged it and release v1.1.0 for this change.