Command Line Tools
wheels generate migration
wheels generate migration
Section titled “wheels generate migration”Generate database migration files using templates.
Synopsis
Section titled “Synopsis”wheels generate migration name=<migrationName> [options]
# Can also be used as:wheels g migration name=<migrationName> [options]CommandBox Parameter Syntax
Section titled “CommandBox Parameter Syntax”- Named parameters:
param=value(e.g.,name=CreateUsersTable,table=users) - Flag parameters:
--flagequalsflag=true(e.g.,--forceequalsforce=true) - Param with value:
--param=valueequalsparam=value(e.g.,--description="User management")
Recommended: Use named parameters: wheels generate migration name=CreateUsersTable --create=users
Description
Section titled “Description”The wheels generate migration command creates database migration files using pre-built templates. Migrations provide version control for your database schema, allowing you to incrementally modify your database structure and roll back changes when needed. The command intelligently detects migration type from the name pattern and uses appropriate templates with transaction handling and error management.
Arguments
Section titled “Arguments”| Argument | Description | Default |
|---|---|---|
name | Migration name (e.g., CreateUsersTable, AddEmailToUsers) | Required |
Migration Name Conventions
Section titled “Migration Name Conventions”- Must start with a letter
- Can contain letters, numbers, and underscores
- Use PascalCase for readability
- Should describe the migration action clearly
Common Patterns:
Create[Table]Table- Creates a new tableAdd[Column]To[Table]- Adds column(s) to existing tableRemove[Column]From[Table]- Removes column(s) from tableRename[OldColumn]To[NewColumn]- Renames a columnChange[Column]In[Table]- Modifies column type/propertiesCreateIndexOn[Table]- Adds an indexRemoveIndexFrom[Table]- Removes an index
Options
Section titled “Options”| Option | Description | Valid Values | Default |
|---|---|---|---|
create | Table name to create (forces create_table type) | Valid table name | "" |
table | Table name to modify (for column operations) | Valid table name | "" |
drop | Table name to drop (forces remove_table type) | Valid table name | "" |
description | Migration description (added as hint) | Any descriptive text | "" |
force | Overwrite existing migration file | true, false | false |
Migration Types and Templates
Section titled “Migration Types and Templates”The command automatically detects the migration type and uses the appropriate template:
| Type | Template | Detected Pattern | Example |
|---|---|---|---|
| Create Table | create-table.txt | Create*Table | CreateUsersTable |
| Remove Table | remove-table.txt | Drop*Table, Remove*Table | DropUsersTable |
| Add Column | create-column.txt | Add*To* | AddEmailToUsers |
| Remove Column | remove-column.txt | Remove*From* | RemoveAgeFromUsers |
| Change Column | change-column.txt | Change*In* | ChangeNameInUsers |
| Rename Column | rename-column.txt | Rename*To* | RenameFirstnameToFullname |
| Add Index | create-index.txt | CreateIndexOn* | CreateIndexOnUsersEmail |
| Remove Index | remove-index.txt | RemoveIndexFrom* | RemoveIndexFromUsers |
| Blank | blank.txt | Any other pattern | CustomMigration |
Examples
Section titled “Examples”Create Table Migration
Section titled “Create Table Migration”wheels generate migration name=CreateUsersTableCreates migration using create-table.txt template with transaction handling.
Create Table with Explicit Table Name
Section titled “Create Table with Explicit Table Name”wheels generate migration name=CreateUsersTable --create=usersForces create_table type and uses “users” as table name.
Add Column Migration
Section titled “Add Column Migration”wheels generate migration name=AddEmailToUsers --table=usersCreates migration using create-column.txt template.
Remove Column Migration
Section titled “Remove Column Migration”wheels generate migration name=RemoveAgeFromUsers --table=usersCreates migration using remove-column.txt template.
Drop Table Migration
Section titled “Drop Table Migration”wheels generate migration name=DropProductsTableCreates migration using remove-table.txt template.
With Description
Section titled “With Description”wheels generate migration name=CreateUsersTable --description="User authentication table"Adds description as hint to the migration component.
Blank/Custom Migration
Section titled “Blank/Custom Migration”wheels generate migration name=MigrateUserData --description="Move user data to new structure"Creates blank migration for custom migration code.
Force Overwrite
Section titled “Force Overwrite”wheels generate migration name=CreateUsersTable --force=trueOverwrites existing migration file.
Generated Code Examples
Section titled “Generated Code Examples”Create Table Migration (Using Template)
Section titled “Create Table Migration (Using Template)”component extends="wheels.migrator.Migration" hint="CreateUsersTable" {
function up() { transaction { try { t = createTable(name = 'users', force='false', id='true', primaryKey='id'); t.timestamps(); t.create(); } catch (any e) { local.exception = e; }
if (StructKeyExists(local, "exception")) { transaction action="rollback"; Throw(errorCode = "1", detail = local.exception.detail, message = local.exception.message, type = "any"); } else { transaction action="commit"; } } }
function down() { transaction { try { dropTable('users'); } catch (any e) { local.exception = e; }
if (StructKeyExists(local, "exception")) { transaction action="rollback"; Throw(errorCode = "1", detail = local.exception.detail, message = local.exception.message, type = "any"); } else { transaction action="commit"; } } }
}Add Column Migration (Using Template)
Section titled “Add Column Migration (Using Template)”component extends="wheels.migrator.Migration" hint="AddEmailToUsers" {
function up() { transaction { try { addColumn(table='users', columnType='string', columnName='column_name', default='', null='true', limit='255'); } catch (any e) { local.exception = e; }
if (StructKeyExists(local, "exception")) { transaction action="rollback"; Throw(errorCode = "1", detail = local.exception.detail, message = local.exception.message, type = "any"); } else { transaction action="commit"; } } }
function down() { transaction { try { removeColumn(table='users', columnName='column_name'); } catch (any e) { local.exception = e; }
if (StructKeyExists(local, "exception")) { transaction action="rollback"; Throw(errorCode = "1", detail = local.exception.detail, message = local.exception.message, type = "any"); } else { transaction action="commit"; } } }
}Blank Migration (Using Template)
Section titled “Blank Migration (Using Template)”component extends="wheels.migrator.Migration" hint="MigrateUserData" {
function up() { transaction { try { // your code goes here } catch (any e) { local.exception = e; }
if (StructKeyExists(local, "exception")) { transaction action="rollback"; Throw(errorCode = "1", detail = local.exception.detail, message = local.exception.message, type = "any"); } else { transaction action="commit"; } } }
function down() { transaction { try { // your code goes here } catch (any e) { local.exception = e; }
if (StructKeyExists(local, "exception")) { transaction action="rollback"; Throw(errorCode = "1", detail = local.exception.detail, message = local.exception.message, type = "any"); } else { transaction action="commit"; } } }
}Smart Name Detection
Section titled “Smart Name Detection”The command infers table names from migration name patterns:
Pattern Detection Examples
Section titled “Pattern Detection Examples”| Migration Name | Detected Type | Inferred Table | Template Used |
|---|---|---|---|
CreateUsersTable | create_table | users | create-table.txt |
DropProductsTable | remove_table | products | remove-table.txt |
AddEmailToUsers | create_column | users | create-column.txt |
RemoveAgeFromUsers | remove_column | users | remove-column.txt |
RenameFirstnameToFullname | rename_column | (needs —table) | rename-column.txt |
ChangeStatusInOrders | change_column | orders | change-column.txt |
CreateIndexOnUsersEmail | create_index | users | create-index.txt |
CustomDataMigration | blank | N/A | blank.txt |
Template System
Section titled “Template System”All migrations use templates from /cli/src/templates/dbmigrate/:
Available Templates
Section titled “Available Templates”blank.txt- Empty migration with transaction wrappercreate-table.txt- Create table with timestampsremove-table.txt- Drop table with reversible down()create-column.txt- Add column with optionsremove-column.txt- Remove columnchange-column.txt- Modify column type/propertiesrename-column.txt- Rename columncreate-index.txt- Add index to tableremove-index.txt- Remove index from table
Template Customization
Section titled “Template Customization”You can override default templates by placing custom versions in /app/snippets/dbmigrate/:
# Copy template to customizecp cli/src/templates/dbmigrate/create-table.txt app/snippets/dbmigrate/create-table.txt
# Edit your custom template# Wheels will automatically use your versionTemplate Variables
Section titled “Template Variables”Templates use placeholder variables that are replaced during generation:
| Variable | Description | Example |
|---|---|---|
|DBMigrateDescription| | Migration hint/description | CreateUsersTable |
|tableName| | Table name | users |
|columnName| | Column name | |
|columnType| | Column type | string |
|force| | Force table creation | false |
|id| | Auto-create ID column | true |
|primaryKey| | Primary key name | id |
|allowNull| | Allow NULL values | true |
|limit| | Column length limit | 255 |
|default| | Default value | "" |
|unique| | Unique index | false |
Migration Workflow
Section titled “Migration Workflow”1. Generate Migration
Section titled “1. Generate Migration”wheels generate migration name=CreateUsersTable2. Edit Migration File
Section titled “2. Edit Migration File”Add columns to the migration:
function up() { transaction { try { t = createTable(name = 'users', force='false', id='true', primaryKey='id'); t.string(columnNames='firstName,lastName', allowNull=false); t.string(columnNames='email', allowNull=false, limit=100); t.boolean(columnNames='active', default=true); t.timestamps(); t.create();
// Add index on email addIndex(table='users', columnNames='email', unique=true); } catch (any e) { local.exception = e; }
if (StructKeyExists(local, "exception")) { transaction action="rollback"; Throw(errorCode = "1", detail = local.exception.detail, message = local.exception.message, type = "any"); } else { transaction action="commit"; } }}3. Check Migration Status
Section titled “3. Check Migration Status”wheels dbmigrate info4. Run Migration
Section titled “4. Run Migration”wheels dbmigrate latest5. Rollback if Needed
Section titled “5. Rollback if Needed”wheels dbmigrate downColumn Types
Section titled “Column Types”Common column types available in migrations:
| Method | Database Type | Example |
|---|---|---|
t.string() | VARCHAR(255) | t.string(columnNames='email') |
t.text() | TEXT | t.text(columnNames='bio') |
t.integer() | INTEGER | t.integer(columnNames='age') |
t.biginteger() | BIGINT | t.biginteger(columnNames='views') |
t.decimal() | DECIMAL | t.decimal(columnNames='price', precision=10, scale=2) |
t.float() | FLOAT | t.float(columnNames='rating') |
t.boolean() | BOOLEAN | t.boolean(columnNames='active') |
t.date() | DATE | t.date(columnNames='birthdate') |
t.datetime() | DATETIME | t.datetime(columnNames='registeredAt') |
t.time() | TIME | t.time(columnNames='startTime') |
t.binary() | BLOB | t.binary(columnNames='avatar') |
t.timestamps() | DATETIME | Creates createdAt, updatedAt, and deletedAt (soft-delete marker) |
Best Practices
Section titled “Best Practices”- Descriptive Names: Use clear, action-oriented migration names
- One Change Per Migration: Keep migrations focused on single changes
- Always Include down(): Make migrations reversible when possible
- Use Transactions: Templates include transactions by default
- Test Rollbacks: Always test
down()method works correctly - Index Performance Columns: Add indexes on frequently queried columns
- Document Complex Migrations: Use description parameter for clarity
- Avoid Data in Migrations: Keep migrations schema-only when possible
Common Patterns
Section titled “Common Patterns”Create Table with Relationships
Section titled “Create Table with Relationships”function up() { transaction { try { t = createTable(name = 'posts', force='false', id='true'); t.string(columnNames='title', allowNull=false); t.text(columnNames='content'); t.references(name='userId', references='users'); t.boolean(columnNames='published', default=false); t.timestamps(); t.create();
addIndex(table='posts', columnNames='userId'); } catch (any e) { local.exception = e; } // Transaction handling... }}Add Multiple Columns
Section titled “Add Multiple Columns”function up() { transaction { try { addColumn(table='users', columnType='string', columnName='phoneNumber', limit=20); addColumn(table='users', columnType='boolean', columnName='emailVerified', default=false); addColumn(table='users', columnType='datetime', columnName='lastLoginAt');
addIndex(table='users', columnNames='phoneNumber'); } catch (any e) { local.exception = e; } // Transaction handling... }}Data Migration
Section titled “Data Migration”function up() { transaction { try { // Add new column addColumn(table='users', columnType='string', columnName='fullName');
// Migrate data (use with caution) execute("UPDATE users SET fullName = CONCAT(firstName, ' ', lastName)");
// Remove old columns removeColumn(table='users', columnName='firstName'); removeColumn(table='users', columnName='lastName'); } catch (any e) { local.exception = e; } // Transaction handling... }}Error Handling
Section titled “Error Handling”Migration Already Exists
Section titled “Migration Already Exists”wheels generate migration name=CreateUsersTable# Error: Migration file already exists. Use force=true to overwrite.
# Solution:wheels generate migration name=CreateUsersTable --force=trueInvalid Migration Name
Section titled “Invalid Migration Name”wheels generate migration name="Create Users Table"# Error: Invalid migration name. Use only letters, numbers, and underscores.
# Solution:wheels generate migration name=CreateUsersTableMigration Fails to Run
Section titled “Migration Fails to Run”wheels dbmigrate latest# Error during migration execution
# Check the migration file for syntax errors# Review database logs# Test the down() methodwheels dbmigrate downTemplate Benefits
Section titled “Template Benefits”Using templates provides several advantages:
Transaction Safety - All operations wrapped in transactions Error Handling - Automatic try/catch with rollback Consistency - Same structure across all migrations Best Practices - Templates follow Wheels conventions Customizable - Override templates in /app/snippets/ Maintainability - Centralized template updates
See Also
Section titled “See Also”- wheels dbmigrate latest - Run migrations
- wheels dbmigrate info - Check migration status
- wheels dbmigrate create table - Alternative table creation
- wheels dbmigrate create blank - Alternative blank migration
- wheels generate model - Generate models
- Database Migrations Guide - Migration best practices
- Template System Guide - Customize templates