Skip to content

Commit

Permalink
Merge pull request #12 from go-carrot/br.bulk
Browse files Browse the repository at this point in the history
Bulk Request
  • Loading branch information
BrandonRomano authored Jun 29, 2017
2 parents 3059cde + 4cebba9 commit 5166db7
Show file tree
Hide file tree
Showing 6 changed files with 372 additions and 71 deletions.
20 changes: 0 additions & 20 deletions .gitignore

This file was deleted.

50 changes: 25 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@

[![Build Status](https://travis-ci.org/go-carrot/surf.svg?branch=master)](https://travis-ci.org/go-carrot/surf) [![codecov](https://codecov.io/gh/go-carrot/surf/branch/master/graph/badge.svg)](https://codecov.io/gh/go-carrot/surf) [![Go Report Card](https://goreportcard.com/badge/github.com/go-carrot/surf)](https://goreportcard.com/report/github.com/go-carrot/surf) [![Gitter](https://img.shields.io/gitter/room/nwjs/nw.js.svg)](https://gitter.im/go-carrot/surf)

Surf is a high level datastore worker that provides CRUD operations for your models.
Declaratively convert structs into data access objects.

## In Use

Before I dive into explaining how to use this library, let me first show an example of how you will interface with your models after everthing is set up:
Before I dive into explaining how to use this library, let me first show an example of how you will interface with your models after everything is set up:

```go
// Inserts
Expand Down Expand Up @@ -43,26 +43,26 @@ type Animal struct {
}
```

### Embed a surf.Worker
### Embed a surf.Model

After this is set up, we can now [embed](https://golang.org/doc/effective_go.html#embedding) a `surf.Worker` into our model.
After this is set up, we can now [embed](https://golang.org/doc/effective_go.html#embedding) a `surf.Model` into our model.

```go
type Animal struct {
surf.Worker
surf.Model
Id int `json:"id"`
Name string `json:"name"`
Age int `json:"age"`
}
```

A `surf.Worker` is actually just an interface, so we'll need to decide what type of worker we want to use!
A `surf.Model` is actually just an interface, so we'll need to decide what type of model we want to use!

> There's more information [below](#workers) on `surf.Worker`.
> There's more information [below](#models) on `surf.Model`.
For this example, we are going to be using a `surf.PqWorker`.
For this example, we are going to be using a `surf.PqModel`.

You can make the decision of what `surf.Worker` to pack into your model at run time, but it will probably be easiest to create a constructor type function and create your models through that. Here I provide a constructor type fuction, but also a `Prep` function which will provide you the flexibility to not use the constructor.
You can make the decision of what `surf.Model` to pack into your model at run time, but it will probably be easiest to create a constructor type function and create your models through that. Here I provide a constructor type fuction, but also a `Prep` function which will provide you the flexibility to not use the constructor.

```go
func NewAnimal() *Animal {
Expand All @@ -71,7 +71,7 @@ func NewAnimal() *Animal {
}

func (a *Animal) Prep() *Animal {
a.Worker = &surf.PqWorker{
a.Model = &surf.PqModel{
Database: db.Get(), // This is a *sql.DB, with github.com/lib/pq as a driver
Config: // TODO
}
Expand All @@ -89,12 +89,12 @@ Before going into detail, here is the `Prep` method with a fully filled out Conf

```go
func (a *Animal) Prep() *Animal {
a.Worker = &surf.PqWorker{
a.Model = &surf.PqModel{
Database: db.Get(),
Config: surf.Configuration{
TableName: "animals",
Fields: []surf.Field{
surf.Field{
{
Pointer: &a.Id,
Name: "id",
UniqueIdentifier: true,
Expand All @@ -103,13 +103,13 @@ func (a *Animal) Prep() *Animal {
return pointerInt != 0
},
},
surf.Field{
{
Pointer: &a.Name,
Name: "name",
Insertable: true,
Updatable: true,
},
surf.Field{
{
Pointer: &a.Age,
Name: "age",
Insertable: true,
Expand All @@ -130,7 +130,7 @@ A `surf.Configuration` has two fields, `TableName` and `Fields`.

## surf.Field

A `surf.Field` defines how a `surf.Worker` will interact with a field.
A `surf.Field` defines how a `surf.Model` will interact with a field.

a `surf.Field` contains a few values that determine this interaction:

Expand All @@ -144,11 +144,11 @@ This is the name of the field as specified in the datastore.

#### Insertable

This value specifies if this `surf.Field` is to be considered by the `Insert()` method of our worker.
This value specifies if this `surf.Field` is to be considered by the `Insert()` method of our model.

#### Updatable

This value specifies if this `surf.Field` is to be considered by the `Update()` method of our worker.
This value specifies if this `surf.Field` is to be considered by the `Update()` method of our model.

#### UniqueIdentifier

Expand All @@ -164,8 +164,6 @@ Setting `UniqueIdentifier` to true gives you the following:
- Call `Update()` with this field in the where clause / filter
- Call `Delete()` with this field in the where clause / filter.

> If you are using a `surf.Worker` that is backed by a relational database, it is strongly recommended that column is indexed.
#### IsSet

This is a function that determines if the value in the struct is set or not.
Expand All @@ -183,24 +181,26 @@ IsSet: func(pointer interface{}) bool {
// ...
```

## Workers
## Models

Workers are simply implementations that adhere to the following interface:
Models are simply implementations that adhere to the following interface:

```go
type Worker interface {
type Model interface {
Insert() error
Load() error
Update() error
Delete() error
BulkFetch(BulkFetchConfig, BuildModel) ([]Model, error)
GetConfiguration() *Configuration
}
```

> Right now in this library there is only `surf.PqWorker` written, but I plan to at minimum write a MySQL worker in the near future.
> Right now in this library there is only `surf.PqModel` written, but I plan to at minimum write a MySQL model in the near future.
### surf.PqWorker
### surf.PqModel

`surf.PqWorker` is written on top of [github.com/lib/pq](https://github.com/lib/pq). This provides high level PostgreSQL CRUD operations to your models.
`surf.PqModel` is written on top of [github.com/lib/pq](https://github.com/lib/pq). This converts your struct into a DAO that can speak with PostgreSQL.

## Running Tests

Expand Down
58 changes: 58 additions & 0 deletions bulk_fetch.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package surf

import (
"strings"
)

// OrderByType is an enumeration of the SQL standard order by
type OrderByType int

const (
ORDER_BY_ASC OrderByType = iota
ORDER_BY_DESC
)

// OrderBy is the definition of a single order by clause
type OrderBy struct {
Field string
Type OrderByType
}

// ToString converts an OrderBy to SQL
func (ob *OrderBy) ToString() string {
obType := ""
switch ob.Type {
case ORDER_BY_ASC:
obType = " ASC"
case ORDER_BY_DESC:
obType = " DESC"
}
return ob.Field + obType
}

// BulkFetchConfig is the configuration of a Model.BulkFetch()
type BulkFetchConfig struct {
Limit int
Offset int
OrderBys []OrderBy
}

// ConsumeSortQuery consumes a `sort` query parameter
// and stuffs them into the OrderBys field
func (c *BulkFetchConfig) ConsumeSortQuery(sortQuery string) {
var orderBys []OrderBy
for _, sort := range strings.Split(sortQuery, ",") {
if string(sort[0]) == "-" {
orderBys = append(orderBys, OrderBy{
Field: sort[1:],
Type: ORDER_BY_DESC,
})
} else {
orderBys = append(orderBys, OrderBy{
Field: sort,
Type: ORDER_BY_ASC,
})
}
}
c.OrderBys = orderBys
}
13 changes: 9 additions & 4 deletions worker.go → model.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
package surf

// Worker is the interface that defines the type
// to be embedded on models
type Worker interface {
// Model is the interface that defines the type
// that will be embedded on models
type Model interface {
Insert() error
Load() error
Update() error
Delete() error
BulkFetch(BulkFetchConfig, BuildModel) ([]Model, error)
GetConfiguration() *Configuration
}

// Configuration is the definition of a model
// Configuration is the metadata to be attached to a model
type Configuration struct {
TableName string
Fields []Field
Expand All @@ -25,3 +26,7 @@ type Field struct {
UniqueIdentifier bool
IsSet func(interface{}) bool
}

// BuildModel is a function that is responsible for returning a
// Model that is ready to have GetConfiguration() called
type BuildModel func() Model
Loading

0 comments on commit 5166db7

Please sign in to comment.