Skip to content

Commit

Permalink
Merge pull request #17 from kohkimakimoto/update-lazyprops
Browse files Browse the repository at this point in the history
Update lazyprops
  • Loading branch information
kohkimakimoto committed Aug 19, 2023
2 parents e4f6eeb + 304ddf8 commit 2cb97d0
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 32 deletions.
16 changes: 11 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,17 +127,23 @@ inertia.Render(c, http.StatusOK, "Index", map[string]interface{}{
// ALWAYS included on first visit...
// OPTIONALLY included on partial reloads...
// ONLY evaluated when needed...
"users": func() interface{} {
users := // get users...
"users": func() (interface{}, error) {
users, err := // get users...
if err != nil {
return nil, err
}
return users
},

// NEVER included on first visit
// OPTIONALLY included on partial reloads
// ONLY evaluated when needed
"users": inertia.Lazy(func() interface{} {
users := // get users...
return users
"users": inertia.Lazy(func() (interface{}, error) {
users, err := // get users...
if err != nil {
return nil, err
}
return users, nil
}),
})
```
Expand Down
10 changes: 7 additions & 3 deletions inertia.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,9 @@ func (i *Inertia) render(code int, component string, props, viewData map[string]
props = filteredProps
}

evaluateProps(props)
if err := evaluateProps(props); err != nil {
return err
}

page := &Page{
Component: component,
Expand Down Expand Up @@ -179,13 +181,15 @@ func (i *Inertia) renderHTML(code int, name string, data map[string]interface{})
return i.c.HTMLBlob(code, buf.Bytes())
}

type LazyPropFunc func() (interface{}, error)

type LazyProp struct {
callback func() interface{}
callback LazyPropFunc
}

// Lazy defines a lazy evaluated data.
// see https://inertiajs.com/partial-reloads#lazy-data-evaluation
func Lazy(callback func() interface{}) *LazyProp {
func Lazy(callback LazyPropFunc) *LazyProp {
return &LazyProp{
callback: callback,
}
Expand Down
8 changes: 4 additions & 4 deletions inertia_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,8 +239,8 @@ func TestInertia_Render(t *testing.T) {
"key2": func() interface{} {
return "value2"
},
"key3": Lazy(func() interface{} {
return "value3"
"key3": Lazy(func() (interface{}, error) {
return "value3", nil
}),
})
if err != nil {
Expand Down Expand Up @@ -288,8 +288,8 @@ func TestInertia_Render(t *testing.T) {
"key2": func() interface{} {
return "value2"
},
"key3": Lazy(func() interface{} {
return "value3"
"key3": Lazy(func() (interface{}, error) {
return "value3", nil
}),
})
if err != nil {
Expand Down
19 changes: 16 additions & 3 deletions util.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,28 @@ func splitAndRemoveEmpty(s string, sep string) []string {
}

// evaluateProps evaluates the given props and update it.
func evaluateProps(values map[string]interface{}) {
func evaluateProps(values map[string]interface{}) error {
for k, v := range values {
switch converted := v.(type) {
case map[string]interface{}:
evaluateProps(converted)
if err := evaluateProps(converted); err != nil {
return err
}
case *LazyProp:
values[k] = converted.callback()
vv, err := converted.callback()
if err != nil {
return err
}
values[k] = vv
case func() (interface{}, error):
vv, err := converted()
if err != nil {
return err
}
values[k] = vv
case func() interface{}:
values[k] = converted()
}
}
return nil
}
80 changes: 63 additions & 17 deletions util_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package inertia

import (
"errors"
"reflect"
"testing"
)

Expand Down Expand Up @@ -111,27 +113,71 @@ func TestSplitAndRemoveEmpty(t *testing.T) {
}

func TestEvaluateProps(t *testing.T) {
a := map[string]interface{}{
"a": "aaa",
"b": map[string]interface{}{
"b-a": "b-aaa",
"b-b": map[string]interface{}{
"b-b-a": "b-b-aaa",
tests := []struct {
values map[string]interface{}
expected map[string]interface{}
error bool
}{
{
values: map[string]interface{}{
"a": "aaa",
"b": map[string]interface{}{
"b-a": "b-aaa",
"b-b": map[string]interface{}{
"b-b-a": "b-b-aaa",
},
},
"c": Lazy(func() (interface{}, error) {
return "ccc", nil
}),
"d": func() interface{} {
return "ddd"
},
},
expected: map[string]interface{}{
"a": "aaa",
"b": map[string]interface{}{
"b-a": "b-aaa",
"b-b": map[string]interface{}{
"b-b-a": "b-b-aaa",
},
},
"c": "ccc",
"d": "ddd",
},
error: false,
},
"c": Lazy(func() interface{} {
return "ccc"
}),
"d": func() interface{} {
return "ddd"
{
values: map[string]interface{}{
"a": func() (interface{}, error) {
return nil, errors.New("error")
},
},
error: true,
},
{
values: map[string]interface{}{
"a": Lazy(func() (interface{}, error) {
return nil, errors.New("error")
},
),
},
error: true,
},
}

evaluateProps(a)
if a["c"] != "ccc" {
t.Errorf("expected 'ccc' but %v", a["c"])
}
if a["d"] != "ddd" {
t.Errorf("expected 'ddd' but %v", a["d"])
for _, tt := range tests {
err := evaluateProps(tt.values)
if tt.error && err == nil {
t.Errorf("expected error but nil")
}
if !tt.error {
if err != nil {
t.Errorf("expected nil but %v", err)
}
if !reflect.DeepEqual(tt.expected, tt.values) {
t.Errorf("expected %v but %v", tt.expected, tt.values)
}
}
}
}

0 comments on commit 2cb97d0

Please sign in to comment.