This skill should be used when the user asks about "migrations", "database schema", "create_table", "add_column", "remove_column", "add_index", "foreign keys", "db:migrate", "db:rollback", "schema.rb", "change_column", "reversible", "references", "timestamps", or needs guidance on modifying database structure in Rails applications.
Provides guidance for creating and managing Rails database migrations with ActiveRecord.
npx claudepluginhub bastos/ruby-plugin-marketplaceThis skill inherits all available tools. When active, it can use any tool Claude has access to.
references/migration-patterns.mdComprehensive guide to creating and managing database migrations in Rails.
# Standalone migration
rails generate migration AddPartNumberToProducts part_number:string
# Create table
rails generate migration CreateProducts name:string price:decimal
# Add reference/foreign key
rails generate migration AddUserRefToProducts user:references
# Add index
rails generate migration AddIndexToUsersEmail
Migration names determine auto-generated code:
| Pattern | Generated Code |
|---|---|
AddColumnToTable | add_column :table, :column, :type |
RemoveColumnFromTable | remove_column :table, :column, :type |
CreateTable | create_table block |
AddIndexToTable | add_index :table, :column |
File format: YYYYMMDDHHMMSS_migration_name.rb
| Type | Description |
|---|---|
:string | Short text (VARCHAR, default 255) |
:text | Long text (unlimited) |
:integer | Standard integer |
:bigint | Large integer (default for PKs in Rails 5.1+) |
:float | Floating point |
:decimal | Precise decimal (use for money) |
:boolean | True/false |
:date | Date only |
:time | Time only |
:datetime | Date and time |
:timestamp | Same as datetime |
:binary | Binary data |
:json | JSON (native if supported) |
:jsonb | Binary JSON (PostgreSQL) |
:uuid | UUID type |
:references | Foreign key column |
add_column :products, :name, :string,
null: false, # NOT NULL constraint
default: "Untitled", # Default value
limit: 100, # Max length (string) or bytes (integer)
precision: 8, # Total digits (decimal)
scale: 2, # Digits after decimal
index: true, # Create index
unique: true, # Unique index
comment: "Product name" # Database comment
class CreateProducts < ActiveRecord::Migration[7.1]
def change
create_table :products do |t|
t.string :name, null: false
t.text :description
t.decimal :price, precision: 10, scale: 2
t.integer :quantity, default: 0
t.boolean :active, default: true
t.references :category, foreign_key: true
t.references :user, null: false, foreign_key: true
t.timestamps # created_at and updated_at
end
add_index :products, :name
add_index :products, [:category_id, :active]
end
end
class AddFieldsToProducts < ActiveRecord::Migration[7.1]
def change
change_table :products do |t|
t.string :sku
t.remove :temporary_field
t.rename :old_name, :new_name
t.index :sku, unique: true
end
end
end
def change
drop_table :products do |t|
# Include schema for reversibility
t.string :name
t.timestamps
end
end
def change
add_column :products, :weight, :decimal, precision: 8, scale: 2
add_column :products, :dimensions, :json
add_column :users, :role, :string, default: "member", null: false
end
def change
# Include type for reversibility
remove_column :products, :discontinued, :boolean, default: false
end
def change
rename_column :products, :upc, :sku
end
# Not automatically reversible - use up/down
def up
change_column :products, :price, :decimal, precision: 12, scale: 2
change_column_null :products, :name, false
change_column_default :products, :status, from: nil, to: "draft"
end
def down
change_column :products, :price, :decimal, precision: 10, scale: 2
change_column_null :products, :name, true
change_column_default :products, :status, from: "draft", to: nil
end
def change
# Adds category_id column with index and foreign key
add_reference :products, :category, foreign_key: true
# Polymorphic reference
add_reference :comments, :commentable, polymorphic: true, index: true
# Without foreign key constraint
add_reference :products, :supplier, foreign_key: false
# Nullable reference
add_reference :products, :brand, null: true, foreign_key: true
end
def change
add_foreign_key :articles, :authors
# Custom column name
add_foreign_key :articles, :users, column: :author_id
# On delete behavior
add_foreign_key :comments, :articles, on_delete: :cascade
add_foreign_key :orders, :users, on_delete: :nullify
# Remove foreign key
remove_foreign_key :articles, :authors
remove_foreign_key :articles, column: :author_id
end
def change
# Basic index
add_index :users, :email
# Unique index
add_index :users, :email, unique: true
# Composite index
add_index :products, [:category_id, :status]
# Partial index (PostgreSQL)
add_index :orders, :shipped_at, where: "shipped_at IS NOT NULL"
# Named index
add_index :products, :sku, name: "idx_products_sku"
# Remove index
remove_index :users, :email
remove_index :products, name: "idx_products_sku"
end
Auto-reversible operations (use change):
add_column / remove_column (with type)add_foreign_key / remove_foreign_keyadd_index / remove_indexadd_reference / remove_referenceadd_timestamps / remove_timestampscreate_table / drop_table (with block)create_join_table / drop_join_tablerename_columnrename_indexrename_tablechange_column_default (with :from and :to)change_column_nulldef change
create_table :products do |t|
t.string :name
t.timestamps
end
reversible do |dir|
dir.up do
execute <<-SQL
CREATE INDEX idx_products_search ON products
USING gin(to_tsvector('english', name));
SQL
end
dir.down do
execute "DROP INDEX idx_products_search;"
end
end
end
def up
change_column :products, :price, :decimal, precision: 12, scale: 2
end
def down
change_column :products, :price, :decimal, precision: 10, scale: 2
end
def up
drop_table :legacy_products
end
def down
raise ActiveRecord::IrreversibleMigration
end
# Run pending migrations
rails db:migrate
# Migrate to specific version
rails db:migrate VERSION=20240101120000
# Rollback last migration
rails db:rollback
# Rollback multiple migrations
rails db:rollback STEP=3
# Redo last migration (rollback + migrate)
rails db:migrate:redo
# Check migration status
rails db:migrate:status
# Run in specific environment
rails db:migrate RAILS_ENV=production
# Create database
rails db:create
# Drop database
rails db:drop
# Reset (drop + create + migrate)
rails db:reset
# Setup (create + load schema + seed)
rails db:setup
# Prepare (idempotent setup)
rails db:prepare
# Load schema directly (faster than migrations)
rails db:schema:load
# Dump current schema
rails db:schema:dump
# Run seeds
rails db:seed
change_column_default with :from and :toreferences)rails db:migrate:redo# Instead of data in migrations, use:
# lib/tasks/data_migration.rake
namespace :data do
desc "Migrate user status values"
task migrate_status: :environment do
User.where(status: "old_value").update_all(status: "new_value")
end
end
class AddIndexToUsersEmail < ActiveRecord::Migration[7.1]
disable_ddl_transaction!
def change
add_index :users, :email, algorithm: :concurrently
end
end
references/migration-patterns.md - Complex migration patterns, zero-downtime migrationsActivates when the user asks about AI prompts, needs prompt templates, wants to search for prompts, or mentions prompts.chat. Use for discovering, retrieving, and improving prompts.
Search, retrieve, and install Agent Skills from the prompts.chat registry using MCP tools. Use when the user asks to find skills, browse skill catalogs, install a skill for Claude, or extend Claude's capabilities with reusable AI agent components.
Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.