347 lines
9.2 KiB
Markdown
347 lines
9.2 KiB
Markdown
# Issues and Fixes for models_ledger Package
|
|
|
|
After reviewing the code in the models_ledger package, the following issues need to be fixed to align with the guidelines in the HeroModel instructions.
|
|
|
|
## 1. Missing API Description and Example Methods
|
|
|
|
### Issue
|
|
All model structs are missing the required `description()` and `example()` methods that are necessary for API documentation and testing.
|
|
|
|
### Fix
|
|
Add the following methods to each model struct (Account, Asset, DNSZone, Group, Member, Notary, Signature, Transaction, User, UserKVS, UserKVSItem):
|
|
|
|
```v
|
|
// API description method
|
|
pub fn (self ModelName) description(methodname string) string {
|
|
match methodname {
|
|
'set' { return 'Create or update a [model]. Returns the ID of the [model].' }
|
|
'get' { return 'Retrieve a [model] by ID. Returns the [model] object.' }
|
|
'delete' { return 'Delete a [model] by ID.' }
|
|
'exist' { return 'Check if a [model] exists by ID. Returns true or false.' }
|
|
'list' { return 'List all [models]. Returns an array of [model] objects.' }
|
|
else { return 'This is a method for [model] object' }
|
|
}
|
|
}
|
|
|
|
// API example method
|
|
pub fn (self ModelName) example(methodname string) (string, string) {
|
|
match methodname {
|
|
'set' {
|
|
return '{"model": {...}}', '1'
|
|
}
|
|
'get' {
|
|
return '{"id": 1}', '{...}'
|
|
}
|
|
'delete' {
|
|
return '{"id": 1}', 'true'
|
|
}
|
|
'exist' {
|
|
return '{"id": 1}', 'true'
|
|
}
|
|
'list' {
|
|
return '{}', '[{...}]'
|
|
}
|
|
else {
|
|
return '{}', '{}'
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
Replace `[model]` and fill in the example data with appropriate values for each model.
|
|
|
|
## 2. Missing API Handler Functions
|
|
|
|
### Issue
|
|
Each model requires an API handler function that processes RPC requests. These are missing for all models.
|
|
|
|
### Fix
|
|
Add handler functions for each model following this pattern:
|
|
|
|
```v
|
|
pub fn modelname_handle(mut f ModelsFactory, rpcid int, servercontext map[string]string, userref UserRef, method string, params string) !Response {
|
|
match method {
|
|
'get' {
|
|
id := db.decode_u32(params)!
|
|
res := f.modelname.get(id)!
|
|
return new_response(rpcid, json.encode_pretty(res))
|
|
}
|
|
'set' {
|
|
mut args := db.decode_generic[ModelNameArg](params)!
|
|
mut o := f.modelname.new(args)!
|
|
if args.id != 0 {
|
|
o.id = args.id
|
|
}
|
|
o = f.modelname.set(o)!
|
|
return new_response_int(rpcid, int(o.id))
|
|
}
|
|
'delete' {
|
|
id := db.decode_u32(params)!
|
|
f.modelname.delete(id)!
|
|
return new_response_true(rpcid)
|
|
}
|
|
'exist' {
|
|
id := db.decode_u32(params)!
|
|
if f.modelname.exist(id)! {
|
|
return new_response_true(rpcid)
|
|
} else {
|
|
return new_response_false(rpcid)
|
|
}
|
|
}
|
|
'list' {
|
|
ids := f.modelname.list()!
|
|
mut result := []ModelName{}
|
|
for id in ids {
|
|
result << f.modelname.get(id)!
|
|
}
|
|
return new_response(rpcid, json.encode_pretty(result))
|
|
}
|
|
else {
|
|
return new_error(rpcid,
|
|
code: 32601
|
|
message: 'Method ${method} not found on modelname'
|
|
)
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## 3. Missing Import for json Module
|
|
|
|
### Issue
|
|
The API handler functions require the json module for encoding responses, but this import is missing.
|
|
|
|
### Fix
|
|
Add the following import to each model file:
|
|
```v
|
|
import json
|
|
```
|
|
|
|
## 4. Incomplete List Method Implementation
|
|
|
|
### Issue
|
|
The current list method simply returns all models without filtering capabilities or pagination.
|
|
|
|
### Fix
|
|
Update the list method to support filtering and pagination:
|
|
|
|
```v
|
|
@[params]
|
|
pub struct ModelNameListArg {
|
|
pub mut:
|
|
filter string
|
|
status int = -1
|
|
limit int = 20
|
|
offset int = 0
|
|
}
|
|
|
|
pub fn (mut self DBModelName) list(args ModelNameListArg) ![]ModelName {
|
|
mut all_models := self.db.list[ModelName]()!.map(self.get(it)!)
|
|
mut filtered_models := []ModelName{}
|
|
|
|
for model in all_models {
|
|
// Add filter logic based on model properties
|
|
if args.filter != '' && !model.name.contains(args.filter) && !model.description.contains(args.filter) {
|
|
continue
|
|
}
|
|
|
|
if args.status >= 0 && int(model.status) != args.status {
|
|
continue
|
|
}
|
|
|
|
filtered_models << model
|
|
}
|
|
|
|
// Apply pagination
|
|
mut start := args.offset
|
|
if start >= filtered_models.len {
|
|
start = 0
|
|
}
|
|
|
|
mut limit := args.limit
|
|
if limit > 100 {
|
|
limit = 100
|
|
}
|
|
|
|
if start + limit > filtered_models.len {
|
|
limit = filtered_models.len - start
|
|
}
|
|
|
|
if limit <= 0 {
|
|
return []ModelName{}
|
|
}
|
|
|
|
return filtered_models[start..start+limit]
|
|
}
|
|
```
|
|
|
|
Adapt the filtering logic based on the specific fields of each model.
|
|
|
|
## 5. Missing or Incomplete Tests
|
|
|
|
### Issue
|
|
The test_utils.v file exists but there are no actual test files for the models.
|
|
|
|
### Fix
|
|
Create test files for each model following the patterns described in README_TESTS.md:
|
|
|
|
1. Create files named `modelname_test.v` for each model
|
|
2. Implement CRUD tests for each model
|
|
3. Implement encoding/decoding tests
|
|
4. Add error handling tests
|
|
5. Add performance tests for complex models
|
|
|
|
Example test file structure:
|
|
```v
|
|
module models_ledger
|
|
|
|
fn test_modelname_crud() {
|
|
mut db := setup_test_db()!
|
|
mut model_db := DBModelName{db: db}
|
|
|
|
// Create test
|
|
mut model := model_db.new(ModelNameArg{...})!
|
|
model = model_db.set(model)!
|
|
assert model.id > 0
|
|
|
|
// Get test
|
|
retrieved := model_db.get(model.id)!
|
|
assert retrieved.field == model.field
|
|
|
|
// Update test
|
|
model.field = new_value
|
|
model = model_db.set(model)!
|
|
retrieved = model_db.get(model.id)!
|
|
assert retrieved.field == new_value
|
|
|
|
// Delete test
|
|
model_db.delete(model.id)!
|
|
assert model_db.exist(model.id)! == false
|
|
}
|
|
```
|
|
|
|
## 6. Missing ModelsFactory Integration
|
|
|
|
### Issue
|
|
There's no ModelsFactory implementation to initialize and manage all models together.
|
|
|
|
### Fix
|
|
Create a `models_factory.v` file with the following structure:
|
|
|
|
```v
|
|
module models_ledger
|
|
|
|
import incubaid.herolib.hero.db
|
|
|
|
pub struct ModelsFactory {
|
|
pub mut:
|
|
db &db.DB
|
|
account &DBAccount
|
|
asset &DBAsset
|
|
dnszone &DBDNSZone
|
|
group &DBGroup
|
|
member &DBMember
|
|
notary &DBNotary
|
|
signature &DBSignature
|
|
transaction &DBTransaction
|
|
user &DBUser
|
|
userkvs &DBUserKVS
|
|
userkvsitem &DBUserKVSItem
|
|
}
|
|
|
|
pub fn new_models_factory(mut database db.DB) !&ModelsFactory {
|
|
mut factory := &ModelsFactory{
|
|
db: database
|
|
}
|
|
|
|
factory.account = &DBAccount{db: database}
|
|
factory.asset = &DBAsset{db: database}
|
|
factory.dnszone = &DBDNSZone{db: database}
|
|
factory.group = &DBGroup{db: database}
|
|
factory.member = &DBMember{db: database}
|
|
factory.notary = &DBNotary{db: database}
|
|
factory.signature = &DBSignature{db: database}
|
|
factory.transaction = &DBTransaction{db: database}
|
|
factory.user = &DBUser{db: database}
|
|
factory.userkvs = &DBUserKVS{db: database}
|
|
factory.userkvsitem = &DBUserKVSItem{db: database}
|
|
|
|
return factory
|
|
}
|
|
```
|
|
|
|
## 7. Update delete() Method Return Type
|
|
|
|
### Issue
|
|
Current delete() methods don't return a boolean value indicating success, which is needed for API handlers.
|
|
|
|
### Fix
|
|
Update the delete() method in all models:
|
|
|
|
```v
|
|
pub fn (mut self DBModelName) delete(id u32) !bool {
|
|
if !self.db.exists[ModelName](id)! {
|
|
return false
|
|
}
|
|
self.db.delete[ModelName](id)!
|
|
return true
|
|
}
|
|
```
|
|
|
|
## 8. Missing Validation in Model Creation
|
|
|
|
### Issue
|
|
The new() methods don't validate input data before creating models.
|
|
|
|
### Fix
|
|
Add validation logic to each new() method:
|
|
|
|
```v
|
|
pub fn (mut self DBModelName) new(args ModelNameArg) !ModelName {
|
|
// Validate required fields
|
|
if args.required_field.trim_space() == '' {
|
|
return error('required_field cannot be empty')
|
|
}
|
|
|
|
// Validate numeric ranges
|
|
if args.numeric_field < min_value || args.numeric_field > max_value {
|
|
return error('numeric_field must be between ${min_value} and ${max_value}')
|
|
}
|
|
|
|
// Create the object
|
|
mut o := ModelName{...}
|
|
|
|
return o
|
|
}
|
|
```
|
|
|
|
## 9. Fix Imports in test_utils.v
|
|
|
|
### Issue
|
|
The test_utils.v file uses a simplified db.new() call that may not work correctly.
|
|
|
|
### Fix
|
|
Update the setup_test_db() function:
|
|
|
|
```v
|
|
fn setup_test_db() !db.DB {
|
|
return db.new(path: ':memory:')!
|
|
}
|
|
```
|
|
|
|
## Implementation Plan
|
|
|
|
1. First, fix test_utils.v to ensure tests can run properly
|
|
2. Create a models_factory.v file
|
|
3. Update each model file to:
|
|
- Add missing imports
|
|
- Add description() and example() methods
|
|
- Update the list() method with filtering capabilities
|
|
- Fix the delete() method return type
|
|
- Add validation to new() methods
|
|
4. Create test files for each model
|
|
5. Create API handler functions for each model
|
|
6. Create an integration test file to test the entire models factory
|
|
|
|
This approach ensures all models are consistent with the required patterns and properly integrated.
|