Skip to content
Draft
1 change: 1 addition & 0 deletions META6.json
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@
"Red::Migration::Column": "lib/Red/Migration/Column.rakumod",
"Red::Migration::Migration": "lib/Red/Migration/Migration.rakumod",
"Red::Migration::Table": "lib/Red/Migration/Table.rakumod",
"Red::ModelRegistry": "lib/Red/ModelRegistry.rakumod",
"Red::Model": "lib/Red/Model.rakumod",
"Red::Operators": "lib/Red/Operators.rakumod",
"Red::Phaser": "lib/Red/Phaser.rakumod",
Expand Down
98 changes: 98 additions & 0 deletions docs/VERSIONED_MODELS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# Red Versioned Models Documentation

## Overview

Red now supports versioned models through the `Red::ModelRegistry` module. This addresses the migration issue by providing a way to manage multiple versions of the same logical model without running into Raku's redeclaration errors.

## The Problem

The original issue was that Raku doesn't allow multiple declarations of the same symbol with different versions:

```raku
model User:ver<0.1> { ... }
model User:ver<0.2> { ... } # ← Error: Redeclaration of symbol 'User'
```

## The Solution

Instead of trying to use the same model name with different versions, we use different model names but register them as versions of the same logical model:

```raku
use Red "experimental migrations";
use Red::ModelRegistry;

# Define different versions using different names
model UserV01 {
has Str $.name is column;
has Int $.age is column;
}

model UserV02 {
has Str $.name is column;
has Str $.full-name is column;
has Int $.age is column;
}

# Register them as versions of the logical "User" model
register-model-version('User', '0.1', UserV01);
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot instead of a function, could it be a trait to be used on the model?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implemented trait-based model registration using is model-version('LogicalName:Version') syntax. The trait automatically registers models with the ModelRegistry. Alternative hash syntax is also supported: is model-version({ name => 'Model', version => '1.0' }).

Commit: d35a029

register-model-version('User', '0.2', UserV02);

# Retrieve models by logical name and version
my $v01 = get-model-version('User', '0.1');
my $v02 = get-model-version('User', '0.2');

# Setup migrations between versions
$v02.^migration: {
.full-name = "{ .name } (migrated from v0.1)"
};
```

## API Reference

### Registration Functions

- `register-model-version($logical-name, $version, $model-class)` - Register a model as a version
- `get-model-version($logical-name, $version)` - Retrieve a specific model version
- `list-model-versions($logical-name)` - List all versions of a logical model
- `get-latest-model-version($logical-name)` - Get the latest version of a model
- `list-all-models()` - List all registered logical models

### Migration Support

The versioned models work seamlessly with Red's existing migration infrastructure:

```raku
# Setup migration from v0.1 to v0.2
$v02.^migration: {
.full-name = "{ .name } (migrated)"
};

# The migration system tracks changes
$v02.^dump-migrations;
```

## Benefits

1. **No Redeclaration Errors** - Uses different physical model names
2. **Logical Versioning** - Maps to logical model versions
3. **Red Integration** - Works with existing Red migration infrastructure
4. **Flexibility** - Supports complex migration scenarios
5. **Testing** - Easy to test different model versions

## Example Usage

See `t/95-versioned-migration-solution.rakutest` for a comprehensive example demonstrating:

- Model registration across multiple versions
- Migration setup between versions
- Instance creation and usage
- Integration with Red's migration system

## Future Enhancements

This foundation enables future enhancements such as:

- CLI tooling for migration generation
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot could you implement that?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implemented comprehensive CLI tooling with Red::Cli::Migration including:

  • Migration template generation (migration-generate)
  • Status monitoring (migration-status)
  • Safety checks (migration-safety-check)
  • Batch advancement (migration-advance-all)
  • Support for both column-change and table-change migration types

Commit: d35a029

- Automatic migration path discovery
- Schema diffing between versions
- Database migration execution
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot isn't that the point of this PR?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're absolutely right! Removed "Database migration execution" from future enhancements since it's already implemented as the core feature of this PR.

Commit: d35a029

Loading