<%- package model_basename -%> <%- store_name = "#{model.name}Store" -%> <%- import "context" import "fmt" import "google.golang.org/appengine/datastore" import "google.golang.org/appengine/log" import "#{config.go_package}/model" import :goon, "#{config.go_package}/stores/goon_store" model_name = "model.#{model.name}" -%> type <%= store_name %>Binder interface { Query(q *datastore.Query) *datastore.Query Visible(m *model.<%= model.name %>) bool Prepare(m *model.<%= model.name %>) } type <%= store_name %> struct{ Binder <%= store_name %>Binder <%- if model.parent -%> ParentKey *datastore.Key <%- end -%> } func (s *<%= store_name %>) All(ctx context.Context) ([]*<%= model_name %>, error) { return s.Select(ctx, s.Query(ctx)) } func (s *<%= store_name %>) Select(ctx context.Context, q *datastore.Query) ([]*<%= model_name %>, error) { g := goon.FromContext(ctx) r := []*<%= model_name %>{} log.Infof(ctx, "q is %v\n", q) _, err := g.GetAll(q.EventualConsistency(), &r) if err != nil { log.Errorf(ctx, "Failed to Select <%= model_name %> because of %v\n", err) return nil, err } return r, nil } func (s *<%= store_name %>) CountBy(ctx context.Context, q *datastore.Query) (int, error) { g := goon.FromContext(ctx) c, err := g.Count(q) if err != nil { log.Errorf(ctx, "Failed to count <%= model_name %> with %v because of %v\n", q, err) return 0, err } return c, nil } func (s *<%= store_name %>) Query(ctx context.Context) *datastore.Query { g := goon.FromContext(ctx) k := g.Kind(new(<%= model_name %>)) // log.Infof(ctx, "Kind for <%= model_name %> is %v\n", k) q := datastore.NewQuery(k) if s.Binder != nil { q = s.Binder.Query(q) } return q } func (s *<%= store_name %>) ByID(ctx context.Context, <%= model.id_name_var %> <%= model.id_golang_type %>) (*<%= model_name %>, error) { <%- if model.parent -%> r := <%= model_name %>{ParentKey: s.ParentKey, <%= model.id_name %>: <%= model.id_name_var %>} <%- else -%> r := <%= model_name %>{<%= model.id_name %>: <%= model.id_name_var %>} <%- end -%> err := s.Get(ctx, &r) if err != nil { return nil, err } return &r, nil } func (s *<%= store_name %>) ByKey(ctx context.Context, key *datastore.Key) (*<%= model_name %>, error) { if err := s.IsValidKey(ctx, key); err != nil { log.Errorf(ctx, "<%= store_name %>.ByKey got Invalid key: %v because of %v\n", key, err) return nil, err } return s.ByID(ctx, key.IntID()) } func (s *<%= store_name %>) Get(ctx context.Context, m *<%= model_name %>) error { g := goon.FromContext(ctx) err := g.Get(m) if err != nil { log.Errorf(ctx, "Failed to Get <%= model_name %> because of %v\n", err) return err } <%- if model.parent -%> if err := s.ValidateParent(m); err != nil { log.Errorf(ctx, "Invalid parent key for <%= model_name %> because of %v\n", err) return err } <%- end -%> if s.Binder != nil && !s.Binder.Visible(m) { return datastore.ErrNoSuchEntity } return nil } func (s *<%= store_name %>) IsValidKey(ctx context.Context, key *datastore.Key) error { if key == nil { return fmt.Errorf("key is nil") } g := goon.FromContext(ctx) expected := g.Kind(&<%= model_name %>{}) if key.Kind() != expected { return fmt.Errorf("key kind must be %s but was %s", expected, key.Kind()) } <%- if model.parent -%> if key.Parent() == nil { return fmt.Errorf("key parent must not be nil but was nil") } <%- end -%> return nil } func (s *<%= store_name %>) Exist(ctx context.Context, m *<%= model_name %>) (bool, error) { if m.ID == <%= model.id_field.zero_value_expression %> { return false, nil } g := goon.FromContext(ctx) key, err := g.KeyError(m) if err != nil { log.Errorf(ctx, "Failed to Get Key of %v because of %v\n", m, err) return false, err } _, err = s.ByKey(ctx, key) if err == datastore.ErrNoSuchEntity { return false, nil } else if err != nil { log.Errorf(ctx, "Failed to get existance of %v because of %v\n", m, err) return false, err } else { return true, nil } } func (s *<%= store_name %>) Create(ctx context.Context, m *<%= model_name %>) (*datastore.Key, error) { if err := m.PrepareToCreate(); err != nil { return nil, err } return s.PutWith(ctx, m, func() error { exist, err := s.Exist(ctx, m) if err != nil { return err } if exist { log.Errorf(ctx, "Failed to create %v because of another entity has same key\n", m) return fmt.Errorf("Duplicate <%= model.id_name %> error: %q of %v\n", m.<%= model.id_name %>, m) } return nil }) } func (s *<%= store_name %>) Update(ctx context.Context, m *<%= model_name %>) (*datastore.Key, error) { if err := m.PrepareToUpdate(); err != nil { return nil, err } return s.PutWith(ctx, m, func() error { exist, err := s.Exist(ctx, m) if err != nil { return err } if !exist { log.Errorf(ctx, "Failed to update %v because it doesn't exist\n", m) return fmt.Errorf("No data to update %q of %v\n", m.<%= model.id_name %>, m) } return nil }) } func (s *<%= store_name %>) PutWith(ctx context.Context, m *<%= model_name %>, f func() error) (*datastore.Key, error) { if s.Binder != nil { s.Binder.Prepare(m) } if err := s.Validate(ctx, m); err != nil { return nil, err } if f != nil { if err := f(); err != nil { return nil, err } } return s.Put(ctx, m) } func (s *<%= store_name %>) Put(ctx context.Context, m *<%= model_name %>) (*datastore.Key, error) { <%- if model.goon['id_type'] == 'UUID' -%> <%- import "github.com/goadesign/goa/uuid" -%> if m.Id == "" { m.Id = uuid.NewV4().String() } <%- end -%> <%- if model.parent -%> if err := s.ValidateParent(m); err != nil { log.Errorf(ctx, "Invalid parent key for <%= model_name %> because of %v\n", err) return nil, err } <%- end -%> g := goon.FromContext(ctx) key, err := g.Put(m) if err != nil { log.Errorf(ctx, "Failed to Put %v because of %v\n", m, err) return nil, err } return key, nil } <%- if model.parent -%> func (s *<%= store_name %>) ValidateParent(m *<%= model_name %>) error { if s.ParentKey == nil { return nil } if m.ParentKey == nil { m.ParentKey = s.ParentKey } if !s.ParentKey.Equal(m.ParentKey) { return fmt.Errorf("Invalid ParentKey for %v", m) } return nil } <%- end -%> func (s *<%= store_name %>) Delete(ctx context.Context, m *<%= model_name %>) error { g := goon.FromContext(ctx) key, err := g.KeyError(m) if err != nil { log.Errorf(ctx, "Failed to Get key of %v because of %v\n", m, err) return err } if err := g.Delete(key); err != nil { log.Errorf(ctx, "Failed to Delete %v because of %v\n", m, err) return err } return nil } func (s *<%= store_name %>) ValidateUniqueness(ctx context.Context, m *<%= model_name %>) error { conditions := map[string]interface{}{ <%- model.fields.select(&:unique?).each do |field| -%> "<%= field.name %>": m.<%= field.name %>, <%- end -%> } for field, value := range conditions { q := s.Query(ctx).Filter(field + " =", value) c, err := s.CountBy(ctx, q) if err != nil { return err } b := 0 if m.IsPersisted() { b = 1 } if c > b { return &model.ValidationError{ Field: field, Message: fmt.Sprintf("%v has already been taken", value), } } } return nil }