ruskit 0.1.5

A modern web framework for Rust inspired by Laravel
Documentation
{% extends "docs_base.html" %}

{% block content %}
<div class="prose prose-slate max-w-none">
    <h1>Database Migrations</h1>

    <p>Ruskit provides a robust database migration system that ensures your database schema changes are versioned, ordered, and can be rolled out consistently across different environments.</p>

    <h2>Migration Commands</h2>

    <h3>Create a New Model with Migration</h3>
    <pre><code class="language-bash">cargo kit make:model Post</code></pre>

    <p>This will:</p>
    <ol>
        <li>Create a new model file at <code>src/app/models/post.rs</code></li>
        <li>Add the model to <code>src/app/models/mod.rs</code></li>
        <li>Create an initial migration with timestamp prefix (e.g., <code>1739885809_create_posts_table</code>)</li>
        <li>Set up basic model structure with id, created_at, and updated_at fields</li>
    </ol>

    <h3>Add a New Migration to Existing Model</h3>
    <pre><code class="language-bash">cargo kit make:migration add_email_to_users --model User</code></pre>

    <p>This will:</p>
    <ol>
        <li>Add a new migration to the specified model's migrations vector</li>
        <li>Automatically prefix the migration with a timestamp (e.g., <code>1739885809_add_email_to_users</code>)</li>
        <li>Create placeholders for UP and DOWN migrations</li>
    </ol>

    <h3>Run Migrations</h3>
    <pre><code class="language-bash">cargo kit migrate</code></pre>

    <p>This will:</p>
    <ol>
        <li>Discover all models in your application</li>
        <li>Collect all migrations from these models</li>
        <li>Sort migrations by timestamp to ensure consistent order</li>
        <li>Run any migrations that haven't been executed yet</li>
    </ol>

    <h3>Fresh Migrations</h3>
    <pre><code class="language-bash">cargo kit migrate:fresh</code></pre>

    <p>This command will:</p>
    <ol>
        <li>Drop all tables in your database (including the migrations table)</li>
        <li>Re-run all migrations from scratch</li>
    </ol>

    <p>This is useful when you want to:</p>
    <ul>
        <li>Reset your database to a clean state</li>
        <li>Test your migrations work correctly from a fresh start</li>
        <li>Resolve issues with inconsistent migration states</li>
    </ul>

    <p>Note: This command will delete all data in your database. Use with caution in production environments.</p>

    <h2>Migration Structure</h2>

    <p>Each migration consists of:</p>
    <ol>
        <li>A unique name with timestamp prefix (e.g., <code>1739885809_create_users_table</code>)</li>
        <li>An UP migration (the changes to apply)</li>
        <li>A DOWN migration (how to reverse the changes)</li>
    </ol>

    <p>Example migration:</p>
    <pre><code class="language-rust">Migration::new(
    "1739885809_add_email_to_users",
    // UP migration
    "ALTER TABLE users ADD COLUMN email TEXT;",
    // DOWN migration
    "ALTER TABLE users DROP COLUMN email;"
)</code></pre>

    <h2>Migration Ordering</h2>

    <p>Migrations are automatically ordered by their timestamp prefix, ensuring that:</p>
    <ol>
        <li>Migrations run in the order they were created</li>
        <li>New migrations always run after existing ones</li>
        <li>The order is consistent across all environments</li>
    </ol>

    <h2>Best Practices</h2>

    <ol>
        <li><strong>One Change Per Migration</strong>: Each migration should handle one specific change (e.g., adding a column, creating a table)</li>
        <li><strong>Meaningful Names</strong>: Use descriptive names for migrations:
            <ul>
                <li><code>create_users_table</code></li>
                <li><code>add_email_to_users</code></li>
                <li><code>add_foreign_key_to_posts</code></li>
            </ul>
        </li>
        <li><strong>Always Include DOWN Migrations</strong>: Make sure your DOWN migrations correctly reverse the changes made in UP migrations</li>
        <li><strong>Run Migrations Immediately</strong>: After creating a new migration, run <code>cargo kit migrate</code> to apply it</li>
        <li><strong>Version Control</strong>: Commit your migrations along with related code changes</li>
    </ol>

    <h2>Migration Files</h2>

    <p>Migrations are stored in your model files under the <code>migrations()</code> function:</p>

    <pre><code class="language-rust">impl Model for User {
    fn migrations() -> Vec<Migration> {
        vec![
            Migration::new(
                "1739885800_create_users_table",
                "CREATE TABLE users (...)",
                "DROP TABLE users"
            ),
            Migration::new(
                "1739885809_add_email_to_users",
                "ALTER TABLE users ADD COLUMN email TEXT;",
                "ALTER TABLE users DROP COLUMN email;"
            ),
        ]
    }
}</code></pre>

    <h2>Migration Table</h2>

    <p>Ruskit maintains a <code>migrations</code> table in your database to track which migrations have been run:</p>

    <pre><code class="language-sql">CREATE TABLE migrations (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    batch INTEGER NOT NULL,
    migration_time INTEGER NOT NULL
)</code></pre>

    <p>This ensures that:</p>
    <ol>
        <li>Each migration runs exactly once</li>
        <li>Migrations can be rolled back by batch</li>
        <li>You can track when each migration was applied</li>
    </ol>
</div>
{% endblock %}