type registery

This commit is contained in:
Niko Abeler 2023-06-25 21:54:04 +02:00
parent 229f5833e0
commit 5d97d87c9b
5 changed files with 71 additions and 41 deletions

51
app/entry_register.go Normal file
View File

@ -0,0 +1,51 @@
package app
import (
"errors"
"owl-blogs/domain/model"
"reflect"
)
type EntryTypeRegistry struct {
types map[string]model.Entry
}
func NewEntryTypeRegistry() *EntryTypeRegistry {
return &EntryTypeRegistry{types: map[string]model.Entry{}}
}
func (r *EntryTypeRegistry) entryType(entry model.Entry) string {
return reflect.TypeOf(entry).Elem().Name()
}
func (r *EntryTypeRegistry) Register(entry model.Entry) error {
t := r.entryType(entry)
if _, ok := r.types[t]; ok {
return errors.New("entry type already registered")
}
r.types[t] = entry
return nil
}
func (r *EntryTypeRegistry) Types() []model.Entry {
types := []model.Entry{}
for _, t := range r.types {
types = append(types, t)
}
return types
}
func (r *EntryTypeRegistry) TypeName(entry model.Entry) (string, error) {
t := r.entryType(entry)
if _, ok := r.types[t]; !ok {
return "", errors.New("entry type not registered")
}
return t, nil
}
func (r *EntryTypeRegistry) Type(name string) (model.Entry, error) {
if _, ok := r.types[name]; !ok {
return nil, errors.New("entry type not registered")
}
return r.types[name], nil
}

View File

@ -3,7 +3,6 @@ package repository
import "owl-blogs/domain/model"
type EntryRepository interface {
RegisterEntryType(entry model.Entry) error
Create(entry model.Entry) error
Update(entry model.Entry) error
Delete(entry model.Entry) error

View File

@ -3,6 +3,7 @@ package infra
import (
"encoding/json"
"errors"
"owl-blogs/app"
"owl-blogs/app/repository"
"owl-blogs/domain/model"
"reflect"
@ -22,8 +23,8 @@ type sqlEntry struct {
}
type DefaultEntryRepo struct {
types map[string]model.Entry
db *sqlx.DB
typeRegistry *app.EntryTypeRegistry
db *sqlx.DB
}
// Create implements repository.EntryRepository.
@ -33,8 +34,8 @@ func (r *DefaultEntryRepo) Create(entry model.Entry) error {
return errors.New("entry already exists")
}
t := r.entryType(entry)
if _, ok := r.types[t]; !ok {
t, err := r.typeRegistry.TypeName(entry)
if err != nil {
return errors.New("entry type not registered")
}
@ -43,7 +44,7 @@ func (r *DefaultEntryRepo) Create(entry model.Entry) error {
metaDataJson, _ = json.Marshal(entry.MetaData())
}
_, err := r.db.Exec("INSERT INTO entries (id, type, content, published_at, meta_data) VALUES (?, ?, ?, ?, ?)", entry.ID(), t, entry.Content(), entry.PublishedAt(), metaDataJson)
_, err = r.db.Exec("INSERT INTO entries (id, type, content, published_at, meta_data) VALUES (?, ?, ?, ?, ?)", entry.ID(), t, entry.Content(), entry.PublishedAt(), metaDataJson)
return err
}
@ -101,16 +102,6 @@ func (r *DefaultEntryRepo) FindById(id string) (model.Entry, error) {
return r.sqlEntryToEntry(data)
}
// RegisterEntryType implements repository.EntryRepository.
func (r *DefaultEntryRepo) RegisterEntryType(entry model.Entry) error {
t := r.entryType(entry)
if _, ok := r.types[t]; ok {
return errors.New("entry type already registered")
}
r.types[t] = entry
return nil
}
// Update implements repository.EntryRepository.
func (r *DefaultEntryRepo) Update(entry model.Entry) error {
exEntry, _ := r.FindById(entry.ID())
@ -118,8 +109,8 @@ func (r *DefaultEntryRepo) Update(entry model.Entry) error {
return errors.New("entry not found")
}
t := r.entryType(entry)
if _, ok := r.types[t]; !ok {
_, err := r.typeRegistry.TypeName(entry)
if err != nil {
return errors.New("entry type not registered")
}
@ -128,11 +119,11 @@ func (r *DefaultEntryRepo) Update(entry model.Entry) error {
metaDataJson, _ = json.Marshal(entry.MetaData())
}
_, err := r.db.Exec("UPDATE entries SET content = ?, published_at = ?, meta_data = ? WHERE id = ?", entry.Content(), entry.PublishedAt(), metaDataJson, entry.ID())
_, err = r.db.Exec("UPDATE entries SET content = ?, published_at = ?, meta_data = ? WHERE id = ?", entry.Content(), entry.PublishedAt(), metaDataJson, entry.ID())
return err
}
func NewEntryRepository(db Database) repository.EntryRepository {
func NewEntryRepository(db Database, register *app.EntryTypeRegistry) repository.EntryRepository {
sqlxdb := db.Get()
// Create tables if not exists
@ -147,18 +138,14 @@ func NewEntryRepository(db Database) repository.EntryRepository {
`)
return &DefaultEntryRepo{
types: map[string]model.Entry{},
db: sqlxdb,
db: sqlxdb,
typeRegistry: register,
}
}
func (r *DefaultEntryRepo) entryType(entry model.Entry) string {
return reflect.TypeOf(entry).Elem().Name()
}
func (r *DefaultEntryRepo) sqlEntryToEntry(entry sqlEntry) (model.Entry, error) {
e, ok := r.types[entry.Type]
if !ok {
e, err := r.typeRegistry.Type(entry.Type)
if err != nil {
return nil, errors.New("entry type not registered")
}
metaData := reflect.New(reflect.TypeOf(e.MetaData()).Elem()).Interface()

View File

@ -1,6 +1,7 @@
package infra_test
import (
"owl-blogs/app"
"owl-blogs/app/repository"
"owl-blogs/infra"
"owl-blogs/test"
@ -12,21 +13,12 @@ import (
func setupRepo() repository.EntryRepository {
db := test.NewMockDb()
repo := infra.NewEntryRepository(db)
repo.RegisterEntryType(&test.MockEntry{})
register := app.NewEntryTypeRegistry()
register.Register(&test.MockEntry{})
repo := infra.NewEntryRepository(db, register)
return repo
}
func TestRepoRegister(t *testing.T) {
db := test.NewMockDb()
repo := infra.NewEntryRepository(db)
err := repo.RegisterEntryType(&test.MockEntry{})
require.NoError(t, err)
err = repo.RegisterEntryType(&test.MockEntry{})
require.Error(t, err)
}
func TestRepoCreate(t *testing.T) {
repo := setupRepo()

View File

@ -8,7 +8,8 @@ import (
func main() {
db := infra.NewSqliteDB("owlblogs.db")
repo := infra.NewEntryRepository(db)
registry := app.NewEntryTypeRegistry()
repo := infra.NewEntryRepository(db, registry)
entryService := app.NewEntryService(repo)
webApp := web.NewWebApp(entryService)
webApp.Run()