More fixes for _request

This commit is contained in:
Hein 2025-11-11 11:16:07 +02:00
parent 682716dd31
commit 7b8216b71c
7 changed files with 63 additions and 40 deletions

View File

@ -69,7 +69,7 @@ jobs:
cache: true
- name: Run golangci-lint
uses: golangci/golangci-lint-action@v6
uses: golangci/golangci-lint-action@v9
with:
version: latest
args: --timeout=5m

View File

@ -71,9 +71,9 @@ func (p *NestedCUDProcessor) ProcessNestedCUD(
RelationData: make(map[string]interface{}),
}
// Check if data has a crud_request field that overrides the operation
// Check if data has a _request field that overrides the operation
if requestOp := p.extractCRUDRequest(data); requestOp != "" {
logger.Debug("Found crud_request override: %s", requestOp)
logger.Debug("Found _request override: %s", requestOp)
operation = requestOp
}
@ -92,8 +92,8 @@ func (p *NestedCUDProcessor) ProcessNestedCUD(
regularData := make(map[string]interface{})
for key, value := range data {
// Skip crud_request field in actual data processing
if key == "crud_request" {
// Skip _request field in actual data processing
if key == "_request" {
continue
}
@ -162,9 +162,9 @@ func (p *NestedCUDProcessor) ProcessNestedCUD(
return result, nil
}
// extractCRUDRequest extracts the crud_request field from data if present
// extractCRUDRequest extracts the request field from data if present
func (p *NestedCUDProcessor) extractCRUDRequest(data map[string]interface{}) string {
if request, ok := data["crud_request"]; ok {
if request, ok := data["_request"]; ok {
if requestStr, ok := request.(string); ok {
return strings.ToLower(strings.TrimSpace(requestStr))
}
@ -377,10 +377,10 @@ func (p *NestedCUDProcessor) getTableNameForModel(model interface{}, defaultName
}
// ShouldUseNestedProcessor determines if we should use nested CUD processing
// It checks if the data contains nested relations or a crud_request field
// It checks if the data contains nested relations or a _request field
func ShouldUseNestedProcessor(data map[string]interface{}, model interface{}, relationshipHelper RelationshipInfoProvider) bool {
// Check for crud_request field
if _, hasCRUDRequest := data["crud_request"]; hasCRUDRequest {
// Check for _request field
if _, hasCRUDRequest := data["_request"]; hasCRUDRequest {
return true
}
@ -396,8 +396,8 @@ func ShouldUseNestedProcessor(data map[string]interface{}, model interface{}, re
// Check if data contains any fields that are relations (nested objects or arrays)
for key, value := range data {
// Skip crud_request and regular scalar fields
if key == "crud_request" {
// Skip _request and regular scalar fields
if key == "_request" {
continue
}

View File

@ -294,7 +294,7 @@ func (h *Handler) handleCreate(ctx context.Context, w common.ResponseWriter, dat
logger.Info("Creating records for %s.%s", schema, entity)
// Check if data contains nested relations or crud_request field
// Check if data contains nested relations or _request field
switch v := data.(type) {
case map[string]interface{}:
// Check if we should use nested processing
@ -1003,7 +1003,7 @@ func (h *Handler) RegisterModel(schema, name string, model interface{}) error {
}
// shouldUseNestedProcessor determines if we should use nested CUD processing
// It checks if the data contains nested relations or a crud_request field
// It checks if the data contains nested relations or a _request field
func (h *Handler) shouldUseNestedProcessor(data map[string]interface{}, model interface{}) bool {
return common.ShouldUseNestedProcessor(data, model, h)
}

View File

@ -10,15 +10,15 @@ type GormTableSchemaInterface interface {
}
type GormTableCRUDRequest struct {
CRUDRequest *string `json:"crud_request"`
Request *string `json:"_request"`
}
func (r *GormTableCRUDRequest) SetRequest(request string) {
r.CRUDRequest = &request
r.Request = &request
}
func (r GormTableCRUDRequest) GetRequest() string {
return *r.CRUDRequest
return *r.Request
}
// New interfaces that replace the legacy ones above

View File

@ -1624,7 +1624,7 @@ func filterExtendedOptions(validator *common.ColumnValidator, options ExtendedRe
}
// shouldUseNestedProcessor determines if we should use nested CUD processing
// It checks if the data contains nested relations or a crud_request field
// It checks if the data contains nested relations or a _request field
func (h *Handler) shouldUseNestedProcessor(data map[string]interface{}, model interface{}) bool {
return common.ShouldUseNestedProcessor(data, model, h)
}

View File

@ -26,7 +26,7 @@ func TestDepartmentEmployees(t *testing.T) {
},
}
resp := makeRequest(t, "/test/departments", deptPayload)
resp := makeRequest(t, "/departments", deptPayload)
assert.Equal(t, http.StatusOK, resp.StatusCode)
// Create employees in department
@ -52,7 +52,7 @@ func TestDepartmentEmployees(t *testing.T) {
},
}
resp = makeRequest(t, "/test/employees", empPayload)
resp = makeRequest(t, "/employees", empPayload)
assert.Equal(t, http.StatusOK, resp.StatusCode)
// Read department with employees
@ -68,7 +68,7 @@ func TestDepartmentEmployees(t *testing.T) {
},
}
resp = makeRequest(t, "/test/departments/dept1", readPayload)
resp = makeRequest(t, "/departments/dept1", readPayload)
assert.Equal(t, http.StatusOK, resp.StatusCode)
var result map[string]interface{}
@ -92,7 +92,7 @@ func TestEmployeeHierarchy(t *testing.T) {
},
}
resp := makeRequest(t, "/test/employees", mgrPayload)
resp := makeRequest(t, "/employees", mgrPayload)
assert.Equal(t, http.StatusOK, resp.StatusCode)
// Update employees to set manager
@ -103,9 +103,9 @@ func TestEmployeeHierarchy(t *testing.T) {
},
}
resp = makeRequest(t, "/test/employees/emp1", updatePayload)
resp = makeRequest(t, "/employees/emp1", updatePayload)
assert.Equal(t, http.StatusOK, resp.StatusCode)
resp = makeRequest(t, "/test/employees/emp2", updatePayload)
resp = makeRequest(t, "/employees/emp2", updatePayload)
assert.Equal(t, http.StatusOK, resp.StatusCode)
// Read manager with reports
@ -121,7 +121,7 @@ func TestEmployeeHierarchy(t *testing.T) {
},
}
resp = makeRequest(t, "/test/employees/mgr1", readPayload)
resp = makeRequest(t, "/employees/mgr1", readPayload)
assert.Equal(t, http.StatusOK, resp.StatusCode)
var result map[string]interface{}
@ -147,7 +147,7 @@ func TestProjectStructure(t *testing.T) {
},
}
resp := makeRequest(t, "/test/projects", projectPayload)
resp := makeRequest(t, "/projects", projectPayload)
assert.Equal(t, http.StatusOK, resp.StatusCode)
// Create project tasks
@ -177,7 +177,7 @@ func TestProjectStructure(t *testing.T) {
},
}
resp = makeRequest(t, "/test/project_tasks", taskPayload)
resp = makeRequest(t, "/project_tasks", taskPayload)
assert.Equal(t, http.StatusOK, resp.StatusCode)
// Create task comments
@ -191,7 +191,7 @@ func TestProjectStructure(t *testing.T) {
},
}
resp = makeRequest(t, "/test/comments", commentPayload)
resp = makeRequest(t, "/comments", commentPayload)
assert.Equal(t, http.StatusOK, resp.StatusCode)
// Read project with all relations
@ -223,7 +223,7 @@ func TestProjectStructure(t *testing.T) {
},
}
resp = makeRequest(t, "/test/projects/proj1", readPayload)
resp = makeRequest(t, "/projects/proj1", readPayload)
assert.Equal(t, http.StatusOK, resp.StatusCode)
var result map[string]interface{}

View File

@ -10,6 +10,8 @@ import (
"os"
"testing"
"github.com/bitechdev/ResolveSpec/pkg/common/adapters/database"
"github.com/bitechdev/ResolveSpec/pkg/common/adapters/router"
"github.com/bitechdev/ResolveSpec/pkg/logger"
"github.com/bitechdev/ResolveSpec/pkg/modelregistry"
"github.com/bitechdev/ResolveSpec/pkg/resolvespec"
@ -117,23 +119,44 @@ func setupTestDB() (*gorm.DB, error) {
func setupTestRouter(db *gorm.DB) http.Handler {
r := mux.NewRouter()
// Create a new registry instance
// Create database adapter
dbAdapter := database.NewGormAdapter(db)
// Create registry
registry := modelregistry.NewModelRegistry()
// Register test models with the registry
// Register test models without schema prefix for SQLite compatibility
// SQLite doesn't support schema prefixes like "test.employees"
testmodels.RegisterTestModels(registry)
// Create handler with GORM adapter and the registry
handler := resolvespec.NewHandlerWithGORM(db)
// Create handler with pre-populated registry
handler := resolvespec.NewHandler(dbAdapter, registry)
// Register test models with the handler for the "test" schema
models := testmodels.GetTestModels()
modelNames := []string{"departments", "employees", "projects", "project_tasks", "documents", "comments"}
for i, model := range models {
handler.RegisterModel("test", modelNames[i], model)
}
// Setup routes without schema prefix for SQLite
// Routes: GET/POST /{entity}, GET/POST/PUT/PATCH/DELETE /{entity}/{id}
r.HandleFunc("/{entity}", func(w http.ResponseWriter, req *http.Request) {
vars := mux.Vars(req)
vars["schema"] = "" // Empty schema for SQLite
reqAdapter := router.NewHTTPRequest(req)
respAdapter := router.NewHTTPResponseWriter(w)
handler.Handle(respAdapter, reqAdapter, vars)
}).Methods("POST")
resolvespec.SetupMuxRoutes(r, handler)
r.HandleFunc("/{entity}/{id}", func(w http.ResponseWriter, req *http.Request) {
vars := mux.Vars(req)
vars["schema"] = "" // Empty schema for SQLite
reqAdapter := router.NewHTTPRequest(req)
respAdapter := router.NewHTTPResponseWriter(w)
handler.Handle(respAdapter, reqAdapter, vars)
}).Methods("POST")
r.HandleFunc("/{entity}", func(w http.ResponseWriter, req *http.Request) {
vars := mux.Vars(req)
vars["schema"] = "" // Empty schema for SQLite
reqAdapter := router.NewHTTPRequest(req)
respAdapter := router.NewHTTPResponseWriter(w)
handler.HandleGet(respAdapter, reqAdapter, vars)
}).Methods("GET")
return r
}