Files
MyClub/UTILITY_CONTROLLERS_README.md
T
Tomas Dvorak 9ccca365b3 dev day #65
2025-10-19 18:09:28 +02:00

9.0 KiB

New Utility Controllers - Summary

Overview

I've added 7 powerful utility controllers that dramatically simplify development and reduce boilerplate code by up to 70%.

What's New

1. Response Helper (response_helper.go)

  • Purpose: Standardized API responses
  • Global Variable: Respond
  • Benefits: Consistent format, easy error handling, metadata support
Respond.Success(c, data, "Success message")
Respond.Created(c, newItem, "Item created")
Respond.NotFound(c, "Item not found")

2. Pagination Helper (pagination_helper.go)

  • Purpose: One-line pagination for any query
  • Global Variable: Paginator
  • Benefits: Auto-extracts params, calculates metadata, supports preloading
meta, err := Paginator.Paginate(c, query, &items)
Respond.SuccessWithMeta(c, items, meta, "Success")

3. Query Helper (query_helper.go)

  • Purpose: Simplified filtering, sorting, and searching
  • Global Variable: QueryParser
  • Benefits: Fluent API, multiple filter types, chain builder
query := QueryParser.BuildQueryChain(c, db).
    WithSearch("title", "content").
    WithSort("created_at", "desc").
    WithBoolFilter("published", "published").
    Build()

4. Validation Helper (validation_helper.go)

  • Purpose: Struct validation with custom validators
  • Global Variable: Validator
  • Benefits: Auto-respond on errors, sanitization, custom validators
if !Validator.ValidateAndRespond(c, req) {
    return // Response already sent
}
title := Validator.SanitizeString(req.Title)

5. Audit Log Controller (audit_log_controller.go)

  • Purpose: Track all important actions
  • Global Variable: AuditLogger
  • Model: models.AuditLog
  • Benefits: Automatic user/IP tracking, before/after changes, searchable logs
AuditLogger.LogCreate(c, "Article", article.ID, "Article created")
AuditLogger.LogUpdate(c, "Article", id, "Updated", before, after)
AuditLogger.LogDelete(c, "Article", id, "Deleted")

6. Batch Operations Controller (batch_operations_controller.go)

  • Purpose: Bulk operations on multiple records
  • Global Variable: BatchOps
  • Benefits: Delete, update, publish, reorder multiple items at once
BatchOps.BatchDelete(c, &models.Article{}, "articles")
BatchOps.BatchPublish(c, &models.Article{}, "articles", true)

7. Export Helper (export_helper.go)

  • Purpose: Export data to CSV/JSON
  • Global Variable: Exporter
  • Benefits: Automatic file download, proper headers
Exporter.ExportToCSV(c, articles, "articles.csv", headers)
Exporter.ExportToJSON(c, articles, "articles.json")

Setup Instructions

Step 1: Install Dependency

go get github.com/go-playground/validator/v10

Step 2: Add Model to Migration

In main.go, add to AutoMigrate:

&models.AuditLog{},

Step 3: Initialize Global Helpers

Add after database initialization in main.go:

// Initialize utility controllers
controllers.InitAuditLogger(dbInstance)
controllers.InitBatchOperations(dbInstance)

Step 4: Use in Controllers

The global variables are ready to use:

  • controllers.Respond
  • controllers.Paginator
  • controllers.QueryParser
  • controllers.Validator
  • controllers.AuditLogger
  • controllers.BatchOps
  • controllers.Exporter

Example: Before vs After

Before (Old Way) - 45 lines

func GetArticles(c *gin.Context) {
    // Parse pagination
    page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
    pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
    if page < 1 {
        page = 1
    }
    if pageSize < 1 || pageSize > 100 {
        pageSize = 20
    }
    offset := (page - 1) * pageSize
    
    // Build query
    query := db.Model(&models.Article{})
    
    // Search
    if search := c.Query("search"); search != "" {
        pattern := "%" + search + "%"
        query = query.Where("title LIKE ? OR content LIKE ?", pattern, pattern)
    }
    
    // Filter
    if published := c.Query("published"); published != "" {
        query = query.Where("published = ?", published == "true")
    }
    
    // Sort
    if sort := c.Query("sort"); sort != "" {
        query = query.Order(sort)
    } else {
        query = query.Order("created_at DESC")
    }
    
    // Count total
    var total int64
    query.Count(&total)
    
    // Execute
    var articles []models.Article
    if err := query.Offset(offset).Limit(pageSize).Find(&articles).Error; err != nil {
        c.JSON(500, gin.H{"error": "Database error"})
        return
    }
    
    // Response
    c.JSON(200, gin.H{
        "data": articles,
        "page": page,
        "total": total,
    })
}

After (New Way) - 11 lines

func GetArticles(c *gin.Context) {
    query := controllers.QueryParser.BuildQueryChain(c, db.Model(&models.Article{})).
        WithSearch("title", "content").
        WithSort("created_at", "desc").
        WithBoolFilter("published", "published").
        Build()

    var articles []models.Article
    meta, _ := controllers.Paginator.Paginate(c, query, &articles)
    controllers.Respond.SuccessWithMeta(c, articles, meta, "Success")
}

Result: 75% less code, more features, better consistency!

Real-World Example

See poll_controller_refactored.go for a complete CRUD controller using all utilities:

  • Pagination with filtering
  • Search and sort
  • Input validation
  • Sanitization
  • Audit logging
  • Batch operations
  • Standardized responses

API Examples

List with Filters

GET /api/v1/articles?search=football&published=true&sort=created_at:desc&page=1&page_size=20

Batch Delete

POST /api/v1/articles/batch-delete
Content-Type: application/json

{"ids": [1, 2, 3, 4, 5]}

Batch Publish

POST /api/v1/articles/batch-publish
Content-Type: application/json

{"ids": [1, 2, 3]}

Export to CSV

GET /api/v1/articles/export/csv

Audit Logs

GET /api/v1/admin/audit-logs?action=CREATE&entity_type=Article&from=2024-01-01

Files Created

  1. internal/controllers/response_helper.go
  2. internal/controllers/pagination_helper.go
  3. internal/controllers/query_helper.go
  4. internal/controllers/validation_helper.go
  5. internal/controllers/audit_log_controller.go
  6. internal/controllers/batch_operations_controller.go
  7. internal/controllers/export_helper.go
  8. internal/controllers/example_usage_controller.go
  9. internal/controllers/poll_controller_refactored.go
  10. internal/models/audit_log.go
  11. DOCS/NEW_UTILITY_CONTROLLERS_GUIDE.md (Complete documentation)

Benefits Summary

Feature Before After Improvement
Code Lines 45 11 75% reduction
Response Format Inconsistent Standardized
Pagination Manual Automatic
Filtering Manual Built-in
Searching Manual Built-in
Sorting Manual Built-in
Validation Manual Automatic
Audit Logging None Automatic
Batch Operations None Built-in
Export None Built-in

Key Improvements

🚀 Productivity

  • Write 70% less code for common operations
  • Faster development with ready-to-use utilities
  • Reduced bugs through standardization

🎯 Consistency

  • Uniform API responses across all endpoints
  • Standard error handling patterns
  • Consistent validation messages

🔧 Maintainability

  • Single source of truth for common operations
  • Easy to update - change once, apply everywhere
  • Better testing - test utilities once

📊 Features

  • Advanced filtering out of the box
  • Full-text search across multiple fields
  • Audit trail for compliance
  • Bulk operations for efficiency
  • Data export for reporting

🛡️ Security

  • Input validation and sanitization
  • Audit logging for accountability
  • Safe batch operations with transaction support

Next Steps

  1. Review documentation: DOCS/NEW_UTILITY_CONTROLLERS_GUIDE.md
  2. Install dependency: go get github.com/go-playground/validator/v10
  3. Add migration: Add &models.AuditLog{} to AutoMigrate
  4. Initialize helpers: Add init calls to main.go
  5. Refactor controllers: Start using utilities in existing controllers
  6. Test endpoints: Try the example API calls

Support

For detailed usage examples, see:

  • 📖 DOCS/NEW_UTILITY_CONTROLLERS_GUIDE.md - Complete guide
  • 💡 internal/controllers/example_usage_controller.go - Usage examples
  • 🔄 internal/controllers/poll_controller_refactored.go - Real refactoring example

Questions?

Each utility controller is well-documented with:

  • Purpose and benefits
  • Usage examples
  • Best practices
  • Common patterns

Start with the guide in DOCS/ and refer to example files for practical implementations.


Your job is now easier, simpler, and better! 🎉