how to use bob's ORM correctly without code generation? #318
-
I'm experimenting with bob as part of making the decision to replace goqu in my project, but can't figure out how to properly use bob's ORM without generating code. The documentation on the site is out of date and now it's completely unclear what to do. I'm trying this code (trying to adapt examples from outdated documentation): package main
import (
"context"
"fmt"
"time"
"github.com/aarondl/opt/omit"
"github.com/stephenafamo/bob"
"github.com/stephenafamo/bob/dialect/psql"
"github.com/stephenafamo/bob/dialect/psql/dialect"
"github.com/stephenafamo/bob/orm"
)
type Docket struct {
DocketID string `db:"docket_id,pk"`
CreateTime time.Time `db:"create_time"`
}
func (d Docket) PrimaryKeyVals() bob.Expression {
return psql.Arg(d.DocketID)
}
type DocketSetter struct {
DocketID omit.Val[string] `db:"docket_id,pk"`
CreateTime omit.Val[time.Time] `db:"create_time"`
orm.Setter[*Docket, *dialect.InsertQuery, *dialect.UpdateQuery]
}
func main() {
table := psql.NewTable[Docket, DocketSetter]("", "dockets")
fmt.Println(table.Insert(DocketSetter{
DocketID: omit.From("123"),
CreateTime: omit.From(time.Now()),
}).MustBuild(context.Background()))
} but I get panic:
By the way, maybe still return an error when using the library API incorrectly, instead of panicking? Thanks! |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
There are other methods in
It is similar to this code: type DocketSetter struct {
DocketID omit.Val[string] `db:"docket_id,pk"`
CreateTime omit.Val[time.Time] `db:"create_time"`
Setter any // orm.Setter is an interface, so when by default, the value is nil
} You should properly implement the setter interface. For example, if the code was generated, it will look something like this: func (s DocketSetter) SetColumns() []string {
vals := make([]string, 0, 2)
if !s.DocketID.IsUnset() {
vals = append(vals, "docket_id")
}
if !s.CreateTime.IsUnset() {
vals = append(vals, "create_time")
}
return vals
}
func (s *DocketSetter) Apply(q *dialect.InsertQuery) {
q.AppendValues(bob.ExpressionFunc(func(ctx context.Context, w io.Writer, d bob.Dialect, start int) ([]any, error) {
vals := make([]bob.Expression, 2)
if s.DocketID.IsUnset() {
vals[0] = psql.Raw("DEFAULT")
} else {
vals[0] = psql.Arg(s.DocketID)
}
if s.CreateTime.IsUnset() {
vals[1] = psql.Raw("DEFAULT")
} else {
vals[1] = psql.Arg(s.CreateTime)
}
return bob.ExpressSlice(ctx, w, d, start, vals, "", ", ", "")
}))
}
func (s VideoSetter) UpdateMod() bob.Mod[*dialect.UpdateQuery] {
return um.Set(s.Expressions()...)
}
func (s VideoSetter) Expressions(prefix ...string) []bob.Expression {
exprs := make([]bob.Expression, 0, 2)
if !s.DocketID.IsUnset() {
exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{
psql.Quote(append(prefix, "docket_id")...),
psql.Arg(s.DocketID),
}})
}
if !s.CreateTime.IsUnset() {
exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{
psql.Quote(append(prefix, "create_time")...),
psql.Arg(s.CreateTime),
}})
}
return exprs
} |
Beta Was this translation helpful? Give feedback.
There are other methods in
orm.Setter[*Docket, *dialect.InsertQuery, *dialect.UpdateQuery]
that need to be implemented.table.Insert
is calling one of those methods (Apply
) and you get a panic because it is nil.It is similar to this code:
You should properly implement the setter interface. For example, if the code was generated, it will look something like this: