-
Notifications
You must be signed in to change notification settings - Fork 4
/
database.go
120 lines (110 loc) · 2.87 KB
/
database.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package main
import (
"encoding/json"
"fmt"
"github.com/segmentio/pointer"
"github.com/zemirco/couchdb"
"github.com/zemirco/todo/item"
)
type database struct {
Client *couchdb.Client
}
const (
// January 1st 2013 01:00:00
past = "1356998400"
// December 24th 3600 12:00:00
future = "32503593600"
)
// CreateUser creates per user database and saves user document to _users database
func (d database) CreateUser(user couchdb.User) error {
// create per user database
if _, err := d.Client.Create(user.Name); err != nil {
return fmt.Errorf("create database: %v", err)
}
// create views in per user database
design := couchdb.DesignDocument{
Document: couchdb.Document{
ID: "_design/todo",
},
Language: "javascript",
Views: map[string]couchdb.DesignDocumentView{
"byCreatedAt": {
Map: `
function(doc) {
if (doc.type === "todo") {
emit(doc.createdAt);
}
}
`,
},
},
}
db := d.Client.Use(user.Name)
if _, err := db.Put(&design); err != nil {
return fmt.Errorf("put design document: %v", err)
}
// create user in _users database
db = d.Client.Use("_users")
if _, err := db.Put(&user); err != nil {
return fmt.Errorf("put user: %v", err)
}
return nil
}
// SaveTodo saves todo item to CouchDB
func (d database) SaveTodo(database string, todo *item.Todo) error {
db := d.Client.Use(database)
if _, err := db.Post(todo); err != nil {
return fmt.Errorf("post todo: %v", err)
}
return nil
}
// GetTodos gets all todos from per user database
func (d database) GetTodos(database string) ([]item.Todo, error) {
db := d.Client.Use(database)
view := db.View("todo")
params := couchdb.QueryParameters{
StartKey: pointer.String(past),
EndKey: pointer.String(future),
IncludeDocs: pointer.Bool(true),
}
res, err := view.Get("byCreatedAt", params)
if err != nil {
return nil, fmt.Errorf("get view byCreatedAt: %v", err)
}
docs := make([]interface{}, len(res.Rows))
for index, row := range res.Rows {
docs[index] = row.Doc
}
todos := make([]item.Todo, len(res.Rows))
b, err := json.Marshal(docs)
if err != nil {
return nil, fmt.Errorf("json marshal: %v", err)
}
return todos, json.Unmarshal(b, &todos)
}
func (d database) GetTodoByID(database, id string) (item.Todo, error) {
db := d.Client.Use(database)
var t item.Todo
return t, db.Get(&t, id)
}
func (d database) UpdateTodo(database string, todo item.Todo) error {
db := d.Client.Use(database)
_, err := db.Put(&todo)
if err != nil {
return fmt.Errorf("put todo: %v", err)
}
return nil
}
func (d database) DeleteTodoByID(database, id string) error {
db := d.Client.Use(database)
// get document first to retrieve current revision
doc, err := d.GetTodoByID(database, id)
if err != nil {
return fmt.Errorf("get todo by id: %v", err)
}
// delete document by id and revision
if _, err = db.Delete(&doc); err != nil {
return fmt.Errorf("delete document: %v", err)
}
return nil
}