Models

Learn how to define and use models in Caesar.

Overview

In Caesar, models are the representation of the data structure of your application. They are defined using the Bun library, and by convention, they are located in the ./app/models folder.

Defining a Model

Here's an example of how to define a model in Caesar:

package models

import (
	"context"
	"time"

	"github.com/rs/xid"
	"github.com/uptrace/bun"
)

// StorageBucket represents a storage bucket in the application.
type StorageBucket struct {
	ID        string `bun:"id,pk"`
	Name      string `bun:"name"`
	Slug      string `bun:"slug,unique"`
	Host      string `bun:"host"`
	KeyId     string `bun:"key_id"`
	SecretKey string `bun:"secret_key"`

	UserID string `bun:"user_id"`
	User   *User  `bun:"rel:belongs-to,join:user_id=id"`
}

// BeforeAppendModel hook to set the ID before inserting a new StorageBucket.
var _ bun.BeforeAppendModelHook = (*StorageBucket)(nil)

func (bucket *StorageBucket) BeforeAppendModel(ctx context.Context, query bun.Query) error {
	switch query.(type) {
	case *bun.InsertQuery:
		bucket.ID = xid.New().String()
	}
	return nil
}

// StorageFile represents a storage file in the application.
type StorageFile struct {
	Size      float64
	Name      string
	UpdatedAt time.Time
	Type      string
}

Annotations

  • bun:"id,pk": Indicates that the field is the primary key.
  • bun:"slug,unique": Specifies that the field must be unique.
  • bun:"rel:belongs-to,join:user_id=id": Specifies the relationship and joining condition.

Hooks

You can use hooks to perform actions before or after database operations. For example, the BeforeAppendModel hook sets the ID field before inserting a new StorageBucket.

Using Models

Once your models are defined, you can use them in your application. Here's an example of how you might use the StorageBucket model:

Inserting a New Record

bucket := &models.StorageBucket{
	Name:      "MyBucket",
	Slug:      "my-bucket",
	Host:      "example.com",
	KeyId:     "key-id",
	SecretKey: "secret-key",
	UserID:    "user-id",
}

// Insert the new bucket into the database.
_, err := db.NewInsert().Model(bucket).Exec(ctx)
if err != nil {
	log.Fatal(err)
}

Querying Records

var buckets []models.StorageBucket
err = db.NewSelect().Model(&buckets).Where("user_id = ?", userID).Scan(ctx)
if err != nil {
	log.Fatal(err)
}

Models can have relationships with other models. For example, the StorageBucket model has a User field, which represents a belongs-to relationship with the User model.

Eager Loading

You can use eager loading to load related models:

var bucket models.StorageBucket
err = db.NewSelect().Model(&bucket).
	Relation("User").
	Where("storage_bucket.id = ?", bucketID).
	Scan(ctx)
if err != nil {
	log.Fatal(err)
}

Summary

Models in Caesar are defined using the Bun library and are located in the ./app/models folder by convention. They represent the data structure of your application and can have relationships with other models. Hooks provide a way to perform actions before or after database operations. Understanding how to define and use models in Caesar will help you manage your application's data more effectively.