feat(api): serve the category content field on GET /_journal/api/v1/categories
- add the nullable TEXT column golem15_journal_categories.content (migration 202610090001) - map it as models.Category.Content and emit category content on every categories row - document the categories row shape and the stored-as-is HTML semantics
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
package updates
|
||||
|
||||
import (
|
||||
"github.com/go-gormigrate/gormigrate/v2"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// addCategoryContent adds the category HTML body (D-21). It must stay the last
|
||||
// migration so RollbackLast drops only this column and keeps the rows.
|
||||
var addCategoryContent = []*gormigrate.Migration{
|
||||
{
|
||||
ID: "202610090001_add_content_to_golem15_journal_categories",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
return tx.Exec(`ALTER TABLE golem15_journal_categories ADD COLUMN IF NOT EXISTS content TEXT NULL`).Error
|
||||
},
|
||||
Rollback: func(tx *gorm.DB) error {
|
||||
return tx.Exec(`ALTER TABLE golem15_journal_categories DROP COLUMN IF EXISTS content`).Error
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
Register(addCategoryContent...)
|
||||
}
|
||||
82
updates/category_content_migration_test.go
Normal file
82
updates/category_content_migration_test.go
Normal file
@@ -0,0 +1,82 @@
|
||||
package updates
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.golem15.com/golem15/summercms/modules/lagoon"
|
||||
"github.com/go-gormigrate/gormigrate/v2"
|
||||
)
|
||||
|
||||
func TestCategoryContentMigration(t *testing.T) {
|
||||
sqlDB := dedicatedDB(t, fmt.Sprintf("journal_catcontent_%d", time.Now().UnixNano()))
|
||||
gdb, err := lagoon.Use(t.Context(), sqlDB)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
backend := gormigrate.New(gdb, &gormigrate.Options{
|
||||
TableName: "summer_migrations_summercms_cabana",
|
||||
UseTransaction: true,
|
||||
}, lagoon.BackendAdminMigrations)
|
||||
if err := backend.Migrate(); err != nil {
|
||||
t.Fatalf("backend_users migrations: %v", err)
|
||||
}
|
||||
m := journalMigrator(gdb)
|
||||
if err := m.Migrate(); err != nil {
|
||||
t.Fatalf("migrate: %v", err)
|
||||
}
|
||||
|
||||
all := All()
|
||||
if last := all[len(all)-1].ID; last != "202610090001_add_content_to_golem15_journal_categories" {
|
||||
t.Fatalf("last migration = %s, want 202610090001_add_content_to_golem15_journal_categories", last)
|
||||
}
|
||||
if !gdb.Migrator().HasColumn("golem15_journal_categories", "content") {
|
||||
t.Fatal("golem15_journal_categories.content missing")
|
||||
}
|
||||
assertUdt(t, gdb, "golem15_journal_categories", "content", "text")
|
||||
var nullable string
|
||||
if err := gdb.WithContext(t.Context()).Raw(
|
||||
`SELECT is_nullable FROM information_schema.columns WHERE table_name = 'golem15_journal_categories' AND column_name = 'content'`,
|
||||
).Scan(&nullable).Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if nullable != "YES" {
|
||||
t.Fatalf("content is_nullable = %q, want YES", nullable)
|
||||
}
|
||||
|
||||
if err := gdb.Exec(`UPDATE golem15_journal_categories SET content = '<p>x</p>' WHERE slug = 'uncategorized'`).Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := m.RollbackLast(); err != nil {
|
||||
t.Fatalf("rollback last: %v", err)
|
||||
}
|
||||
if !gdb.Migrator().HasTable("golem15_journal_categories") {
|
||||
t.Fatal("golem15_journal_categories dropped by the content rollback")
|
||||
}
|
||||
if gdb.Migrator().HasColumn("golem15_journal_categories", "content") {
|
||||
t.Fatal("content column survived rollback")
|
||||
}
|
||||
var rows int64
|
||||
if err := gdb.Raw(`SELECT COUNT(*) FROM golem15_journal_categories WHERE slug = 'uncategorized'`).Scan(&rows).Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if rows != 1 {
|
||||
t.Fatalf("uncategorized rows after rollback = %d, want 1", rows)
|
||||
}
|
||||
|
||||
if err := m.Migrate(); err != nil {
|
||||
t.Fatalf("re-migrate: %v", err)
|
||||
}
|
||||
if !gdb.Migrator().HasColumn("golem15_journal_categories", "content") {
|
||||
t.Fatal("content column missing after re-migrate")
|
||||
}
|
||||
var content sql.NullString
|
||||
if err := gdb.Raw(`SELECT content FROM golem15_journal_categories WHERE slug = 'uncategorized'`).Scan(&content).Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if content.Valid {
|
||||
t.Fatalf("uncategorized content after re-migrate = %q, want NULL", content.String)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user