Add method to automatically create integer IDs
This commit is contained in:
parent
da3a159a46
commit
eabb4d6277
12
README.md
12
README.md
|
@ -51,6 +51,18 @@ if err := db.Delete("fish", ""); err != nil {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Also supports automatically generating integer IDs.
|
||||||
|
|
||||||
|
```
|
||||||
|
// Write a fish to the database
|
||||||
|
fish := Fish{}
|
||||||
|
id, err := db.WriteAutoId("fish", fish); if err != nil {
|
||||||
|
fmt.Println("Error", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ID == 1
|
||||||
|
```
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
- Complete documentation is available on [godoc](http://godoc.org/github.com/nanobox-io/golang-scribble).
|
- Complete documentation is available on [godoc](http://godoc.org/github.com/nanobox-io/golang-scribble).
|
||||||
- Coverage Report is available on [gocover](https://gocover.io/github.com/nanobox-io/golang-scribble)
|
- Coverage Report is available on [gocover](https://gocover.io/github.com/nanobox-io/golang-scribble)
|
||||||
|
|
54
scribble.go
54
scribble.go
|
@ -10,13 +10,15 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/jcelliott/lumber"
|
"github.com/jcelliott/lumber"
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Version is the current version of the project
|
// Version is the current version of the project
|
||||||
const Version = "1.0.4"
|
const Version = "1.0.4"
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
|
||||||
// Logger is a generic logger interface
|
// Logger is a generic logger interface
|
||||||
Logger interface {
|
Logger interface {
|
||||||
Fatal(string, ...interface{})
|
Fatal(string, ...interface{})
|
||||||
|
@ -98,6 +100,11 @@ func (d *Driver) Write(collection, resource string, v interface{}) error {
|
||||||
mutex.Lock()
|
mutex.Lock()
|
||||||
defer mutex.Unlock()
|
defer mutex.Unlock()
|
||||||
|
|
||||||
|
return d.writeFile(collection, resource, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Writes a file to disk
|
||||||
|
func (d *Driver) writeFile(collection string, resource string, v interface{}) error {
|
||||||
//
|
//
|
||||||
dir := filepath.Join(d.dir, collection)
|
dir := filepath.Join(d.dir, collection)
|
||||||
fnlPath := filepath.Join(dir, resource+".json")
|
fnlPath := filepath.Join(dir, resource+".json")
|
||||||
|
@ -123,6 +130,51 @@ func (d *Driver) Write(collection, resource string, v interface{}) error {
|
||||||
return os.Rename(tmpPath, fnlPath)
|
return os.Rename(tmpPath, fnlPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Locks the database, gets the next available integer resource ID and attempts to write the
|
||||||
|
// record to the database under the [collection] specified with the generated [resource] ID
|
||||||
|
func (d *Driver) WriteAutoId(collection string, v interface{}) (resourceId int64, err error) {
|
||||||
|
resourceId = -1
|
||||||
|
|
||||||
|
// ensure there is a place to save record
|
||||||
|
if collection == "" {
|
||||||
|
return resourceId, fmt.Errorf("Missing collection - no place to save record!")
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex := d.getOrCreateMutex(collection)
|
||||||
|
mutex.Lock()
|
||||||
|
defer mutex.Unlock()
|
||||||
|
|
||||||
|
// list the directory, sort it, take the last entry then parse and increment the last ID
|
||||||
|
files, err := ioutil.ReadDir(d.dir)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error listing directory %s: %s", d.dir, err.Error())
|
||||||
|
return resourceId, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(files) == 0 {
|
||||||
|
resourceId = 1
|
||||||
|
} else {
|
||||||
|
lastFile := files[len(files)-1]
|
||||||
|
|
||||||
|
ext := path.Ext(lastFile.Name())
|
||||||
|
|
||||||
|
baseName := strings.TrimSuffix(lastFile.Name(), ext)
|
||||||
|
|
||||||
|
resourceId, err := strconv.ParseInt(baseName, 10, 8)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error parsing string '%s' as integer", baseName, err.Error())
|
||||||
|
return resourceId, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stringResourceId := fmt.Sprintf("%d", resourceId)
|
||||||
|
|
||||||
|
fmt.Printf("Writing resource under auto-generated ID '%s'\n", stringResourceId)
|
||||||
|
err = d.writeFile(collection, stringResourceId, v)
|
||||||
|
|
||||||
|
return resourceId, err
|
||||||
|
}
|
||||||
|
|
||||||
// Read a record from the database
|
// Read a record from the database
|
||||||
func (d *Driver) Read(collection, resource string, v interface{}) error {
|
func (d *Driver) Read(collection, resource string, v interface{}) error {
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ package scribble
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -85,6 +86,36 @@ func TestWriteAndRead(t *testing.T) {
|
||||||
destroySchool()
|
destroySchool()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
func TestWriteAutoIdAndRead(t *testing.T) {
|
||||||
|
|
||||||
|
createDB()
|
||||||
|
|
||||||
|
// add fish to database
|
||||||
|
id, err := db.WriteAutoId(collection, redfish);
|
||||||
|
if err != nil {
|
||||||
|
t.Error("Create fish failed: ", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
if id <= 0 {
|
||||||
|
t.Error("Auto-generated ID should have been > 0")
|
||||||
|
}
|
||||||
|
|
||||||
|
stringId := fmt.Sprintf("%d", id)
|
||||||
|
|
||||||
|
// read fish from database
|
||||||
|
if err := db.Read(collection, stringId, &onefish); err != nil {
|
||||||
|
t.Error("Failed to read: ", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
if onefish.Type != "red" {
|
||||||
|
t.Error("Expected red fish, got: ", onefish.Type)
|
||||||
|
}
|
||||||
|
|
||||||
|
destroySchool()
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
func TestReadall(t *testing.T) {
|
func TestReadall(t *testing.T) {
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user