Skip to content

Instantly share code, notes, and snippets.

@nirasan
Created November 2, 2017 09:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nirasan/1636a45e93608cb457eb149cd8c20ec8 to your computer and use it in GitHub Desktop.
Save nirasan/1636a45e93608cb457eb149cd8c20ec8 to your computer and use it in GitHub Desktop.
package repository
import (
"reflect"
"google.golang.org/appengine/datastore"
"context"
"errors"
)
// 保存するデータの型
type Entity interface {
GetID() int64
}
var EntityType = reflect.TypeOf((*Entity)(nil)).Elem()
// Datastore を操作するレポジトリ型
type CommonRepository struct {
ctx context.Context
kind string
entity Entity
typeName string
}
// レポジトリの作成
func NewCommonRepository(ctx context.Context, e Entity) (*CommonRepository, error) {
rt := reflect.TypeOf(e)
if rt.Kind() != reflect.Ptr || rt.Elem().Kind() != reflect.Struct {
return nil, errors.New("invalid type")
}
r := &CommonRepository{ctx: ctx, entity: e}
r.typeName = rt.String()
r.kind = rt.Elem().String()
return r, nil
}
// 1件取得
func (r *CommonRepository) Find(e Entity) error {
if r.typeName != reflect.TypeOf(e).String() {
return errors.New("infalid type")
}
err := datastore.Get(r.ctx, r.NewKey(e.GetID()), e)
return err
}
// 全件取得
func (r *CommonRepository) FindAll(list interface{}) (error) {
rt := reflect.TypeOf(list)
if rt.Kind() != reflect.Ptr || rt.Elem().Kind() != reflect.Slice || !rt.Elem().Elem().Implements(EntityType) {
return errors.New("invalid type")
}
_, err := datastore.NewQuery(r.kind).GetAll(r.ctx, list)
return err
}
// 作成
func (r *CommonRepository) Create(e Entity) error {
if r.typeName != reflect.TypeOf(e).String() {
return errors.New("infalid type")
}
_, err := datastore.Put(r.ctx, r.NewKey(e.GetID()), e)
return err
}
// 更新
func (r *CommonRepository) Update(e Entity) error {
if r.typeName != reflect.TypeOf(e).String() {
return errors.New("infalid type")
}
_, err := datastore.Put(r.ctx, r.NewKey(e.GetID()), e)
return err
}
// 削除
func (r *CommonRepository) Delete(e Entity) error {
return datastore.Delete(r.ctx, r.NewKey(e.GetID()))
}
// Datastore のキーの作成
func (r *CommonRepository) NewKey(id int64) *datastore.Key {
return datastore.NewKey(r.ctx, r.kind, "", id, nil)
}
package repository
import (
"google.golang.org/appengine"
"google.golang.org/appengine/aetest"
"strings"
"testing"
"google.golang.org/appengine/datastore"
"context"
"fmt"
)
type MyStruct struct {
ID int64
Name string
}
func (s *MyStruct) GetID() int64 {
return s.ID
}
func TestCommonRepository(t *testing.T) {
// aetest (App Engine Test) のインスタンス作成
opt := aetest.Options{StronglyConsistentDatastore: true}
instance, err := aetest.NewInstance(&opt)
if err != nil {
t.Fatalf("Failed to create aetest instance: %v", err)
}
defer instance.Close()
// aetest インスタンスからリクエストの作成
req, _ := instance.NewRequest("GET", "/", strings.NewReader(""))
// コンテキストの取得
ctx := appengine.NewContext(req)
repo, err := NewCommonRepository(ctx, &MyStruct{})
t.Logf("%+v, %+v\n", repo, err)
e1 := &MyStruct{Name: "a", ID: 1}
if err := repo.Create(e1); err != nil {
t.Error(err)
}
e2 := &MyStruct{ID: 1}
err = repo.Find(e2)
t.Logf("%+v, %+v", e2, err)
fmt.Println("#### 1.")
showList(ctx)
list := []*MyStruct{}
err = repo.FindAll(&list)
t.Logf("%+v, %+v, %+v", err, len(list), list)
for _, ee := range list {
t.Logf("%#v", ee)
ee.GetID()
}
e2.Name = "b"
if err = repo.Update(e2); err != nil {
t.Error(err)
}
fmt.Println("#### 2.")
showList(ctx)
if err = repo.Delete(e2); err != nil {
t.Error(err)
}
fmt.Println("#### 3.")
showList(ctx)
}
func showList(ctx context.Context) {
list := []*MyStruct{}
_, err := datastore.NewQuery("repository.MyStruct").GetAll(ctx, &list)
fmt.Printf("error: %+v\n", err)
for _, e := range list {
fmt.Printf("entity: %+v\n", e)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment