Files
herolib/lib/hero/db/ai_instructions_hero_models.md
2025-09-17 05:52:09 +02:00

6.5 KiB

HeroDB Model Creation Instructions for AI

Overview

This document provides clear instructions for AI agents to create new HeroDB models similar to comment.v. These models are used to store structured data in Redis using the HeroDB system.

Key Concepts

  • Each model represents a data type stored in Redis hash sets
  • Models must implement serialization/deserialization using the encoder module
  • Models inherit from the Base struct which provides common fields
  • The database uses a factory pattern for model access

File Structure

Create a new file in lib/hero/heromodels/ with the model name (e.g., calendar.v).

Required Components

1. Model Struct Definition

Define your model struct with the following pattern:

@[heap]
pub struct Calendar {
	db.Base // Inherit from Base struct
pub mut:
	// Add your specific fields here
	title       string
	start_time  i64
	end_time    i64
	location    string
	attendees   []string
}

2. Type Name Method

Implement a method to return the model's type name:

pub fn (self Calendar) type_name() string {
	return 'calendar'
}

3. Serialization (dump) Method

Implement the dump method to serialize your struct's fields using the encoder:

pub fn (self Calendar) dump(mut e &encoder.Encoder) ! {
	e.add_string(self.title)
	e.add_i64(self.start_time)
	e.add_i64(self.end_time)
	e.add_string(self.location)
	e.add_list_string(self.attendees)
}

4. Deserialization (load) Method

Implement the load method to deserialize your struct's fields:

fn (mut self DBCalendar) load(mut o Calendar, mut e &encoder.Decoder) ! {
	o.title = e.get_string()!
	o.start_time = e.get_i64()!
	o.end_time = e.get_i64()!
	o.location = e.get_string()!
	o.attendees = e.get_list_string()!
}

5. Model Arguments Struct

Define a struct for creating new instances of your model:

@[params]
pub struct CalendarArg {
pub mut:
	title      string @[required]
	start_time i64
	end_time   i64
	location   string
	attendees  []string
}

6. Database Wrapper Struct

Create a database wrapper struct for your model:

pub struct DBCalendar {
pub mut:
	db &db.DB @[skip; str: skip]
}

7. Factory Integration

Add your model to the ModelsFactory struct in factory.v:

pub struct ModelsFactory {
pub mut:
	comments DBCalendar
	// ... other models
}

And initialize it in the new() function:

pub fn new() !ModelsFactory {
	mut mydb := db.new()!
	return ModelsFactory{
		comments: DBCalendar{
			db: &mydb
		}
		// ... initialize other models
	}
}

Encoder Methods Reference

Use these methods for serialization/deserialization:

Encoder (Serialization)

  • e.add_bool(val bool)
  • e.add_u8(val u8)
  • e.add_u16(val u16)
  • e.add_u32(val u32)
  • e.add_u64(val u64)
  • e.add_i8(val i8)
  • e.add_i16(val i16)
  • e.add_i32(val i32)
  • e.add_i64(val i64)
  • e.add_f32(val f32)
  • e.add_f64(val f64)
  • e.add_string(val string)
  • e.add_list_bool(val []bool)
  • e.add_list_u8(val []u8)
  • e.add_list_u16(val []u16)
  • e.add_list_u32(val []u32)
  • e.add_list_u64(val []u64)
  • e.add_list_i8(val []i8)
  • e.add_list_i16(val []i16)
  • e.add_list_i32(val []i32)
  • e.add_list_i64(val []i64)
  • e.add_list_f32(val []f32)
  • e.add_list_f64(val []f64)
  • e.add_list_string(val []string)

Decoder (Deserialization)

  • e.get_bool()!
  • e.get_u8()!
  • e.get_u16()!
  • e.get_u32()!
  • e.get_u64()!
  • e.get_i8()!
  • e.get_i16()!
  • e.get_i32()!
  • e.get_i64()!
  • e.get_f32()!
  • e.get_f64()!
  • e.get_string()!
  • e.get_list_bool()!
  • e.get_list_u8()!
  • e.get_list_u16()!
  • e.get_list_u32()!
  • e.get_list_u64()!
  • e.get_list_i8()!
  • e.get_list_i16()!
  • e.get_list_i32()!
  • e.get_list_i64()!
  • e.get_list_f32()!
  • e.get_list_f64()!
  • e.get_list_string()!

CRUD Methods Implementation

Create New Instance

pub fn (mut self DBCalendar) new(args CalendarArg) !Calendar {
	mut o := Calendar{
		title:      args.title
		start_time: args.start_time
		end_time:   args.end_time
		location:   args.location
		attendees:  args.attendees
		updated_at: ourtime.now().unix()
	}
	return o
}

Save to Database

pub fn (mut self DBCalendar) set(o Calendar) !Calendar {
	return self.db.set[Calendar](o)!
}

Retrieve from Database

pub fn (mut self DBCalendar) get(id u32) !Calendar {
	mut o, data := self.db.get_data[Calendar](id)!
	mut e_decoder := encoder.decoder_new(data)
	self.load(mut o, mut e_decoder)!
	return o
}

Delete from Database

pub fn (mut self DBCalendar) delete(id u32) ! {
	self.db.delete[Calendar](id)!
}

Check Existence

pub fn (mut self DBCalendar) exist(id u32) !bool {
	return self.db.exists[Calendar](id)!
}

List All Objects

pub fn (mut self DBCalendar) list() ![]Calendar {
	return self.db.list[Calendar]()!.map(self.get(it)!)
}

Example Usage Script

Create a .vsh script in examples/hero/heromodels/ to demonstrate usage:

#!/usr/bin/env -S v -n -w -cg -gc none -cc tcc -d use_openssl -enable-globals run

import freeflowuniverse.herolib.core.redisclient
import freeflowuniverse.herolib.hero.heromodels

mut mydb := heromodels.new()!

// Create a new object
mut o := mydb.calendar.new(
	title: 'Meeting'
	start_time: 1672531200
	end_time: 1672534800
	location: 'Conference Room'
	attendees: ['john@example.com', 'jane@example.com']
)!

// Save to database
oid := mydb.calendar.set(o)!
println('Created object with ID: ${oid}')

// Retrieve from database
mut o2 := mydb.calendar.get(oid)!
println('Retrieved object: ${o2}')

// List all objects
mut objects := mydb.calendar.list()!
println('All objects: ${objects}')

Best Practices

  1. Always inherit from db.Base struct
  2. Implement all required methods (type_name, dump, load)
  3. Use the encoder methods for consistent serialization
  4. Handle errors appropriately with ! or or blocks
  5. Keep field ordering consistent between dump and load methods
  6. Use snake_case for field names
  7. Add @[required] attribute to mandatory fields in argument structs
  8. Initialize timestamps using ourtime.now().unix()

Implementation Steps Summary

  1. Create model struct inheriting from db.Base
  2. Implement type_name() method
  3. Implement dump() method using encoder
  4. Implement load() method using decoder
  5. Create argument struct with @[params] attribute
  6. Create database wrapper struct
  7. Add model to ModelsFactory in factory.v
  8. Implement CRUD methods
  9. Create example usage script
  10. Test the implementation with the example script