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
|
||||
- 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)
|
||||
|
|
58
scribble.go
58
scribble.go
|
@ -10,13 +10,15 @@ import (
|
|||
"sync"
|
||||
|
||||
"github.com/jcelliott/lumber"
|
||||
"path"
|
||||
"strings"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// Version is the current version of the project
|
||||
const Version = "1.0.4"
|
||||
|
||||
type (
|
||||
|
||||
// Logger is a generic logger interface
|
||||
Logger interface {
|
||||
Fatal(string, ...interface{})
|
||||
|
@ -98,6 +100,11 @@ func (d *Driver) Write(collection, resource string, v interface{}) error {
|
|||
mutex.Lock()
|
||||
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)
|
||||
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)
|
||||
}
|
||||
|
||||
// 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
|
||||
func (d *Driver) Read(collection, resource string, v interface{}) error {
|
||||
|
||||
|
@ -212,11 +264,11 @@ func (d *Driver) Delete(collection, resource string) error {
|
|||
case fi == nil, err != nil:
|
||||
return fmt.Errorf("Unable to find file or directory named %v\n", path)
|
||||
|
||||
// remove directory and all contents
|
||||
// remove directory and all contents
|
||||
case fi.Mode().IsDir():
|
||||
return os.RemoveAll(dir)
|
||||
|
||||
// remove file
|
||||
// remove file
|
||||
case fi.Mode().IsRegular():
|
||||
return os.RemoveAll(dir + ".json")
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package scribble
|
|||
import (
|
||||
"os"
|
||||
"testing"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
//
|
||||
|
@ -85,6 +86,36 @@ func TestWriteAndRead(t *testing.T) {
|
|||
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) {
|
||||
|
||||
|
|
Loading…
Reference in New Issue