1
0
mirror of https://github.com/taigrr/wtf synced 2025-01-18 04:03:14 -08:00

WTF-986 Extract the reflection bits into a Reflective package

Signed-off-by: Chris Cummer <chriscummer@me.com>
This commit is contained in:
Chris Cummer 2020-10-13 21:08:24 -07:00
parent 07f4d3f524
commit 356a998404
3 changed files with 48 additions and 43 deletions

View File

@ -44,7 +44,11 @@ func (widget *Widget) content() (string, string, bool) {
// Dynamically access the droplet to get the requested columns values // Dynamically access the droplet to get the requested columns values
for _, colName := range columnSet { for _, colName := range columnSet {
val := droplet.ValueForColumn(colName) val, err := droplet.StringValueForProperty(colName)
if err != nil {
val = "???"
}
truncVal := utils.Truncate(val, maxColWidth, false) truncVal := utils.Truncate(val, maxColWidth, false)
vals = append(vals, truncVal) vals = append(vals, truncVal)

View File

@ -6,10 +6,9 @@ import (
"strings" "strings"
"github.com/digitalocean/godo" "github.com/digitalocean/godo"
"github.com/wtfutil/wtf/utils"
) )
const invalidColumn = "???"
// Droplet represents WTF's view of a DigitalOcean droplet // Droplet represents WTF's view of a DigitalOcean droplet
type Droplet struct { type Droplet struct {
godo.Droplet godo.Droplet
@ -21,11 +20,13 @@ type Droplet struct {
// Image represents WTF's view of a DigitalOcean droplet image // Image represents WTF's view of a DigitalOcean droplet image
type Image struct { type Image struct {
godo.Image godo.Image
utils.Reflective
} }
// Region represents WTF's view of a DigitalOcean region // Region represents WTF's view of a DigitalOcean region
type Region struct { type Region struct {
godo.Region godo.Region
utils.Reflective
} }
// NewDroplet creates and returns an instance of Droplet // NewDroplet creates and returns an instance of Droplet
@ -35,10 +36,12 @@ func NewDroplet(doDroplet godo.Droplet) *Droplet {
Image{ Image{
*doDroplet.Image, *doDroplet.Image,
utils.Reflective{},
}, },
Region{ Region{
*doDroplet.Region, *doDroplet.Region,
utils.Reflective{},
}, },
} }
@ -47,58 +50,31 @@ func NewDroplet(doDroplet godo.Droplet) *Droplet {
/* -------------------- Exported Functions -------------------- */ /* -------------------- Exported Functions -------------------- */
// ValueForColumn returns a string value for the given column // StringValueForProperty returns a string value for the given column
func (drop *Droplet) ValueForColumn(colName string) string { func (drop *Droplet) StringValueForProperty(propName string) (string, error) {
r := reflect.ValueOf(drop)
f := reflect.Indirect(r).FieldByName(colName)
var strVal string var strVal string
var err error
// Figure out if we should forward this property to a sub-object // Figure out if we should forward this property to a sub-object
// Lets us support "Region.Name" column definitions // Lets us support "Region.Name" column definitions
split := strings.Split(colName, ".") split := strings.Split(propName, ".")
switch split[0] { switch split[0] {
case "Image": case "Image":
strVal = drop.Image.ValueForColumn(split[1]) strVal, err = drop.Image.StringValueForProperty(split[1])
case "Region": case "Region":
strVal = drop.Region.ValueForColumn(split[1]) strVal, err = drop.Region.StringValueForProperty(split[1])
default: default:
if !f.IsValid() { v := reflect.ValueOf(drop)
strVal = invalidColumn refVal := reflect.Indirect(v).FieldByName(propName)
if !refVal.IsValid() {
err = fmt.Errorf("invalid property name: %s", propName)
} else { } else {
strVal = fmt.Sprintf("%v", f) strVal = fmt.Sprintf("%v", refVal)
} }
} }
return strVal return strVal, err
}
// ValueForColumn returns a string value for the given column
func (reg *Image) ValueForColumn(colName string) string {
r := reflect.ValueOf(reg)
f := reflect.Indirect(r).FieldByName(colName)
if !f.IsValid() {
return invalidColumn
}
strVal := fmt.Sprintf("%v", f)
return strVal
}
// ValueForColumn returns a string value for the given column
func (reg *Region) ValueForColumn(colName string) string {
r := reflect.ValueOf(reg)
f := reflect.Indirect(r).FieldByName(colName)
if !f.IsValid() {
return invalidColumn
}
strVal := fmt.Sprintf("%v", f)
return strVal
} }

25
utils/reflective.go Normal file
View File

@ -0,0 +1,25 @@
package utils
import (
"fmt"
"reflect"
)
// Reflective is a convenience wrapper for objects that makes it possible to
// extract property values from the object by property name
type Reflective struct{}
// StringValueForProperty returns a string value for the given property
// If the property doesn't exist, it returns an error
func (ref *Reflective) StringValueForProperty(propName string) (string, error) {
v := reflect.ValueOf(ref)
refVal := reflect.Indirect(v).FieldByName(propName)
if !refVal.IsValid() {
return "", fmt.Errorf("invalid property name: %s", propName)
}
strVal := fmt.Sprintf("%v", refVal)
return strVal, nil
}