Skip to content

Commit

Permalink
chore: some improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
jferrl committed Apr 27, 2024
1 parent 0ed4689 commit 6df2363
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 12 deletions.
2 changes: 1 addition & 1 deletion hook.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,4 @@ const (
// This funcions are used for create hooks that are executed before or after.
// This hooks are able to modify the model before the transaction is executed or
// create some new stuff during the ongoin transaction.
type HookFunc[T Yo] func(context.Context, *Model[T], *spanner.ReadWriteTransaction) error
type HookFunc[T Yoable[T]] func(context.Context, *Model[T], *spanner.ReadWriteTransaction) error
23 changes: 14 additions & 9 deletions yo.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,38 +12,38 @@ import (
// ErrNoClient is returned when the spanner client is not set.
var ErrNoClient = errors.New("no spanner client")

// Yo is the common interface for the generated model.
type Yo interface {
// Yoable is the common interface for the generated model.
type Yoable[Y any] interface {
Insert(ctx context.Context) *spanner.Mutation
Update(ctx context.Context) *spanner.Mutation
InsertOrUpdate(ctx context.Context) *spanner.Mutation
Delete(ctx context.Context) *spanner.Mutation
}

// Opt is a function that modifies a Model.
type Opt[T Yo] func(*Model[T])
type Opt[T Yoable[T]] func(*Model[T])

// WithSpannerClientOption returns an Opt that sets the spanner client.
func WithSpannerClientOption[T Yo](c spanner.Client) Opt[T] {
func WithSpannerClientOption[T Yoable[T]](c spanner.Client) Opt[T] {
return func(m *Model[T]) {
m.Client = c
}
}

// Model is a struct that embeds the generated model and implements the
// Yo interface.
type Model[T Yo] struct {
Yo
type Model[T Yoable[T]] struct {
Yoable[T]
spanner.Client

hooks map[Hook]HookFunc[T]
}

// NewModel returns a new wrapped yo model.
func NewModel[T Yo](m T, opts ...Opt[T]) *Model[T] {
func NewModel[T Yoable[T]](m T, opts ...Opt[T]) *Model[T] {
mo := &Model[T]{
Yo: m,
hooks: make(map[Hook]HookFunc[T]),
Yoable: m,
hooks: make(map[Hook]HookFunc[T]),
}
for _, opt := range opts {
opt(mo)
Expand All @@ -57,6 +57,11 @@ func (m *Model[T]) On(h Hook, f HookFunc[T]) {
m.hooks[h] = f
}

// Model returns the embedded model.
func (m *Model[T]) Model() Yoable[T] {
return m.Yoable
}

// Apply executes a kind of mutation against the database.
// It executes the before hook, the mutation and the after hook.
func (m *Model[T]) Apply(ctx context.Context, mtype Mutation) (time.Time, error) {
Expand Down
9 changes: 7 additions & 2 deletions yo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ func TestModel_Insert(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
m := NewModel(tt.fields.model)

_, ok := m.Model().(*user.User)
if !ok {
t.Fatal("unable to type assert to *user.User")
}

if got := m.Insert(ctx) != nil; !got {
t.Errorf("Model.Insert() = %v, want non-nil", got)
}
Expand Down Expand Up @@ -130,7 +135,7 @@ func TestModel_Apply(t *testing.T) {
mutType: Insert,
before: func(_ context.Context, m *Model[*user.User], _ *spanner.ReadWriteTransaction) error {
// type assertion to access the embedded model
u, ok := m.Yo.(*user.User)
u, ok := m.Yoable.(*user.User)
if !ok {
return errors.New("unable to type assert to *user.User")
}
Expand All @@ -140,7 +145,7 @@ func TestModel_Apply(t *testing.T) {
},
after: func(ctx context.Context, m *Model[*user.User], rwt *spanner.ReadWriteTransaction) error {
// type assertion to access the embedded model
u, ok := m.Yo.(*user.User)
u, ok := m.Yoable.(*user.User)
if !ok {
return errors.New("unable to type assert to *user.User")
}
Expand Down

0 comments on commit 6df2363

Please sign in to comment.