Reputation: 1714
I'm expecting to see the visits
increment with every GET
request to /foo
but it remains as 1
. What am I doing wrong here?
package main
import (
"log"
"github.com/gofiber/fiber/v2"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
// Item model
type Item struct {
gorm.Model
UID int64 `gorm:"primaryKey;autoIncrement"`
Name string `gorm:"index;not null"`
Visits int32 `gorm:"default 0"`
}
func main() {
db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
if err != nil {
panic(err)
}
db.AutoMigrate(&Item{})
db.Create(&Item{
Name: "foo",
})
app := fiber.New(fiber.Config{})
app.Get("/:name", func(c *fiber.Ctx) error {
var i Item
db.First(&i, "name = ?", c.Params("name"))
if i.Name == "" {
return c.Status(fiber.StatusNotFound).JSON(&fiber.Map{
"message": "Not found",
})
}
db.Model(&i).Update("visits", i.Visits+1)
return c.JSON(i)
})
log.Println("Listening...")
log.Fatal(app.Listen(":3000"))
}
Upvotes: 0
Views: 1617
Reputation: 969
If you log the error like:
if err := db.Model(&i).Update("visits", i.Visits+1).Error; err != nil {
fmt.Printf("update err != nil; %v\n", err)
}
You will see that it says: "WHERE conditions required". So, you can fix this like:
if err := db.Model(&i).Where("name = ?", i.Name).Update("visits", i.Visits+1).Error; err != nil {
fmt.Printf("update err != nil; %v\n", err)
}
Here is some more details about Error Handling in GORM
EDIT: There is actually a larger issue at play here with your example. The issue is that you are defining UID
as part of your Item
model which conflicts with what gorm.Model
provides. You can see in Declaring Models the following model definition:
// gorm.Model definition
type Model struct {
ID uint `gorm:"primaryKey"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
}
which when added to your Item
type / model, you would get:
type Item struct {
// gorm.Model
ID uint `gorm:"primaryKey"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
// your fields
UID int64 `gorm:"primaryKey;autoIncrement"`
Name string `gorm:"index;not null"`
Visits int32 `gorm:"default 0"`
}
It seems like this results in your database table being created in a weird state. You might notice in your returned JSON payload that both the ID
AND UID
are equal to 0. And as you start/stop the server multiple times and look at the additional records that are created (because of your db.Create()
at the top) you end up with multiple Items with a name of "foo" all of which having ID
and UID
of 0... this is why GORM is then unable to update the item without a WHERE clause, since the primary keys are not properly set on the table.
If you remove UID from your model (or maybe even just remove "primaryKey" from it) you can then use the Update()
method without the need for the where condition. So, your model should look like:
// Item model
type Item struct {
gorm.Model
Name string `gorm:"index;not null"`
Visits int32 `gorm:"default 0"`
}
After you make changes to your model / type, make sure to delete your test.db
file in order to have the table re-created with the new / correct format.
Lastly, in regards to my original answer, you should also see the errors being logged to your console automatically by GORM without needing to specifically handle them like I suggested.
Upvotes: 1