Skip to content

Commit 7e16dd3

Browse files
author
Jason Raede
committed
Added SaveResult type for better validation error handling
1 parent ab5f21e commit 7e16dd3

File tree

6 files changed

+108
-37
lines changed

6 files changed

+108
-37
lines changed

collection.go

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ package bongo
22

33
import (
44
"errors"
5+
"fmt"
56
"github.com/oleiade/reflections"
67
"labix.org/v2/mgo"
78
"labix.org/v2/mgo/bson"
8-
"log"
9+
// "log"
910
"reflect"
1011
// "math"
1112
// "strings"
@@ -20,10 +21,18 @@ func (c *Collection) Collection() *mgo.Collection {
2021
return c.Connection.Session.DB(c.Connection.Config.Database).C(c.Name)
2122
}
2223

23-
func (c *Collection) Save(mod interface{}) (error, []string) {
24+
func (c *Collection) Save(mod interface{}) (result *SaveResult) {
2425
defer func() {
26+
2527
if r := recover(); r != nil {
26-
log.Fatal("Failed to save:\n", r)
28+
if e, ok := r.(error); ok {
29+
result = NewSaveResult(false, e)
30+
} else if e, ok := r.(string); ok {
31+
result = NewSaveResult(false, errors.New(e))
32+
} else {
33+
result = NewSaveResult(false, errors.New(fmt.Sprint(r)))
34+
}
35+
2736
}
2837
}()
2938

@@ -58,8 +67,9 @@ func (c *Collection) Save(mod interface{}) (error, []string) {
5867
results := reflect.ValueOf(mod).MethodByName("Validate").Call([]reflect.Value{})
5968
if errs, ok := results[0].Interface().([]string); ok {
6069
if len(errs) > 0 {
61-
err := errors.New("Validation failed")
62-
return err, errs
70+
err := NewSaveResult(false, errors.New("Validation failed"))
71+
err.ValidationErrors = errs
72+
return err
6373
}
6474
}
6575
}
@@ -87,7 +97,11 @@ func (c *Collection) Save(mod interface{}) (error, []string) {
8797

8898
_, err = c.Collection().UpsertId(modelMap["_id"], modelMap)
8999

90-
return err, nil
100+
if err != nil {
101+
panic(err)
102+
}
103+
104+
return NewSaveResult(true, nil)
91105
}
92106

93107
func (c *Collection) FindById(id bson.ObjectId, mod interface{}) error {
@@ -113,6 +127,7 @@ func (c *Collection) FindById(id bson.ObjectId, mod interface{}) error {
113127
// Pass in the sample just so we can get the collection name
114128
func (c *Collection) Find(query interface{}) *ResultSet {
115129

130+
// Count for testing
116131
q := c.Collection().Find(query)
117132

118133
resultset := new(ResultSet)
@@ -125,7 +140,7 @@ func (c *Collection) Find(query interface{}) *ResultSet {
125140

126141
func (c *Collection) FindOne(query interface{}, mod interface{}) error {
127142
// Now run a find
128-
results := c.Connection.Find(query, mod)
143+
results := c.Find(query)
129144

130145
hasNext := results.Next(mod)
131146

collection_test.go

Lines changed: 25 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ func (s *TestSuite) TestSaveAndFindWithHooks(c *C) {
1717
message.Msg = "Foo"
1818
message.Count = 5
1919

20-
err, _ := connection.Save(message)
20+
result := connection.Save(message)
2121

22-
c.Assert(err, Equals, nil)
22+
c.Assert(result.Success, Equals, true)
2323

2424
newMessage := new(FooBar)
2525

@@ -33,9 +33,9 @@ func (s *TestSuite) TestSaveAndFindWithHooks(c *C) {
3333
c.Assert(newMessage.Count, Equals, 12)
3434

3535
// Saving it again should run +1 on BeforeSave and +2 on BeforeUpdate
36-
err, _ = connection.Save(message)
36+
result = connection.Save(message)
3737

38-
c.Assert(err, Equals, nil)
38+
c.Assert(result.Success, Equals, true)
3939
c.Assert(message.Count, Equals, 10)
4040

4141
connection.Session.DB(config.Database).DropDatabase()
@@ -55,9 +55,9 @@ func (s *TestSuite) TestSaveAndFindWithChild(c *C) {
5555
Foo: "foo",
5656
BazBing: "bar",
5757
}
58-
err, _ := connection.Save(message)
58+
result := connection.Save(message)
5959

60-
c.Assert(err, Equals, nil)
60+
c.Assert(result.Success, Equals, true)
6161

6262
newMessage := new(FooBar)
6363

@@ -79,10 +79,9 @@ func (s *TestSuite) TestValidationFailure(c *C) {
7979
message.Msg = "Foo"
8080
message.Count = 3
8181

82-
err, errs := connection.Save(message)
83-
84-
c.Assert(err.Error(), Equals, "Validation failed")
85-
c.Assert(errs[0], Equals, "count cannot be 3")
82+
err := connection.Save(message)
83+
c.Assert(err.Error.Error(), Equals, "Validation failed")
84+
c.Assert(err.ValidationErrors[0], Equals, "count cannot be 3")
8685

8786
connection.Session.DB(config.Database).DropDatabase()
8887
}
@@ -112,14 +111,14 @@ func (s *TestSuite) TestDelete(c *C) {
112111
message.Msg = "Foo"
113112
message.Count = 5
114113

115-
err, _ := connection.Save(message)
114+
result := connection.Save(message)
116115

117-
c.Assert(err, Equals, nil)
116+
c.Assert(result.Success, Equals, true)
118117

119118
connection.Delete(message)
120119

121120
newMessage := new(FooBar)
122-
err = connection.FindById(message.Id, newMessage)
121+
err := connection.FindById(message.Id, newMessage)
123122
c.Assert(err.Error(), Equals, "not found")
124123
// Make sure the ids are the same
125124
//
@@ -138,17 +137,17 @@ func (s *TestSuite) TestFindOne(c *C) {
138137
message.Msg = "Foo"
139138
message.Count = 5
140139

141-
err, _ := connection.Save(message)
140+
res := connection.Save(message)
142141

143-
c.Assert(err, Equals, nil)
142+
c.Assert(res.Success, Equals, true)
144143

145144
result := &FooBar{}
146145

147146
query := bson.M{
148147
"count": 7,
149148
}
150149

151-
err = connection.FindOne(query, result)
150+
err := connection.FindOne(query, result)
152151

153152
c.Assert(err, Equals, nil)
154153

@@ -170,17 +169,17 @@ func (s *TestSuite) TestFind(c *C) {
170169
message.Msg = "Foo"
171170
message.Count = 5
172171

173-
err, _ := connection.Save(message)
172+
result := connection.Save(message)
174173

175-
c.Assert(err, Equals, nil)
174+
c.Assert(result.Success, Equals, true)
176175

177176
message2 := new(FooBar)
178177
message2.Msg = "Bar"
179178
message2.Count = 10
180179

181-
err, _ = connection.Save(message2)
180+
result = connection.Save(message2)
182181

183-
c.Assert(err, Equals, nil)
182+
c.Assert(result.Success, Equals, true)
184183

185184
// Now run a find
186185
results := connection.Find(nil, &FooBar{})
@@ -214,17 +213,17 @@ func (s *TestSuite) TestFindWithPagination(c *C) {
214213
message.Msg = "Foo"
215214
message.Count = 5
216215

217-
err, _ := connection.Save(message)
216+
result := connection.Save(message)
218217

219-
c.Assert(err, Equals, nil)
218+
c.Assert(result.Success, Equals, true)
220219

221220
message2 := new(FooBar)
222221
message2.Msg = "Bar"
223222
message2.Count = 5
224223

225-
err, _ = connection.Save(message2)
224+
result = connection.Save(message2)
226225

227-
c.Assert(err, Equals, nil)
226+
c.Assert(result.Success, Equals, true)
228227

229228
// Now run a find (hooks will add 2)
230229
results := connection.Find(&bson.M{"count": 7}, &FooBar{})
@@ -269,8 +268,8 @@ func createAndSaveDocument(conn *Connection) {
269268
Count: 5,
270269
}
271270

272-
err, _ := conn.Save(message)
273-
if err != nil {
271+
err := conn.Save(message)
272+
if err.Error != nil {
274273
panic(err)
275274
}
276275
}

find.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package bongo
22

33
import (
44
"labix.org/v2/mgo"
5-
// "log"
5+
"log"
66
"math"
77
)
88

@@ -37,6 +37,9 @@ func (r *ResultSet) Next(mod interface{}) bool {
3737
InitializeDocumentFromDB(r.Connection.GetEncryptionKey(colname), returnMap, mod)
3838
return true
3939
}
40+
41+
count, err := r.Query.Count()
42+
log.Println("No result", count, err)
4043
return false
4144
}
4245

main.go

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package bongo
22

33
import (
44
// "fmt"
5+
"encoding/json"
56
"github.com/oleiade/reflections"
67
"labix.org/v2/mgo"
78
"labix.org/v2/mgo/bson"
@@ -20,6 +21,29 @@ type Config struct {
2021
EncryptionKeyPerCollection map[string]string
2122
}
2223

24+
type SaveResult struct {
25+
Success bool
26+
Err error
27+
ValidationErrors []string
28+
}
29+
30+
func (s *SaveResult) Error() string {
31+
return s.Err.Error()
32+
}
33+
34+
func NewSaveResult(success bool, err error) *SaveResult {
35+
return &SaveResult{success, err, []string{}}
36+
}
37+
38+
func (s *SaveResult) MarshalJSON() ([]byte, error) {
39+
// If there are validation errors, just return those as an array. Otherwise marshal the error.Error() string
40+
if len(s.ValidationErrors) > 0 {
41+
return json.Marshal(s.ValidationErrors)
42+
} else {
43+
return json.Marshal(s.Err.Error())
44+
}
45+
}
46+
2347
type Connection struct {
2448
Config *Config
2549
Session *mgo.Session
@@ -178,7 +202,7 @@ func (m *Connection) FindOne(query interface{}, mod interface{}) error {
178202
return col.FindOne(query, mod)
179203
}
180204

181-
func (m *Connection) Save(mod interface{}) (error, []string) {
205+
func (m *Connection) Save(mod interface{}) *SaveResult {
182206
col := m.Collection(getCollectionName(mod))
183207

184208
return col.Save(mod)

main_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package bongo
22

33
import (
4+
"encoding/json"
5+
"errors"
6+
// "fmt"
47
. "gopkg.in/check.v1"
58
)
69

@@ -38,3 +41,30 @@ func (s *TestSuite) TestRegister(c *C) {
3841
c.Assert(indexes[1].Key[0], Equals, "count")
3942

4043
}
44+
45+
type errorHolder struct {
46+
Err *SaveResult
47+
}
48+
49+
func (s *TestSuite) TestMarshalResult(c *C) {
50+
51+
err := NewSaveResult(false, errors.New("Failed to save"))
52+
53+
holder := &errorHolder{
54+
Err: err,
55+
}
56+
57+
marshaled, e := json.Marshal(holder)
58+
c.Assert(e, IsNil)
59+
60+
c.Assert(string(marshaled), Equals, `{"Err":"Failed to save"}`)
61+
62+
holder.Err.ValidationErrors = []string{"foo", "bar"}
63+
64+
marshaled, e = json.Marshal(holder)
65+
c.Assert(e, IsNil)
66+
67+
c.Assert(string(marshaled), Equals, `{"Err":["foo","bar"]}`)
68+
// fmt.Println(string(marshaled))
69+
70+
}

validate_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ func (s *TestSuite) TestValidateMongoIdRef(c *C) {
2626
message.Msg = "Foo"
2727
message.Count = 5
2828

29-
err, _ := connection.Save(message)
29+
res := connection.Save(message)
3030

31-
c.Assert(err, Equals, nil)
31+
c.Assert(res.Success, Equals, true)
3232
c.Assert(ValidateMongoIdRef(message.Id, connection.Collection("foo_bar")), Equals, true)
3333
c.Assert(ValidateMongoIdRef(bson.NewObjectId(), connection.Collection("foo_bar")), Equals, false)
3434
c.Assert(ValidateMongoIdRef(bson.NewObjectId(), connection.Collection("other_collection")), Equals, false)

0 commit comments

Comments
 (0)