Back to list
bastos

rails-migrations

by bastos

Bastos' Claude Code Ruby Plugin Marketplace

0🍴 0📅 Jan 24, 2026

SKILL.md


name: rails-migrations description: 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. version: 1.0.0

ActiveRecord Migrations

Comprehensive guide to creating and managing database migrations in Rails.

Creating Migrations

Generator Commands

# 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

Naming Conventions

Migration names determine auto-generated code:

PatternGenerated Code
AddColumnToTableadd_column :table, :column, :type
RemoveColumnFromTableremove_column :table, :column, :type
CreateTablecreate_table block
AddIndexToTableadd_index :table, :column

File format: YYYYMMDDHHMMSS_migration_name.rb

Column Types

TypeDescription
:stringShort text (VARCHAR, default 255)
:textLong text (unlimited)
:integerStandard integer
:bigintLarge integer (default for PKs in Rails 5.1+)
:floatFloating point
:decimalPrecise decimal (use for money)
:booleanTrue/false
:dateDate only
:timeTime only
:datetimeDate and time
:timestampSame as datetime
:binaryBinary data
:jsonJSON (native if supported)
:jsonbBinary JSON (PostgreSQL)
:uuidUUID type
:referencesForeign key column

Column Modifiers

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

Table Operations

Create Table

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

Modify Table

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

Drop Table

def change
  drop_table :products do |t|
    # Include schema for reversibility
    t.string :name
    t.timestamps
  end
end

Column Operations

Add Columns

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

Remove Columns

def change
  # Include type for reversibility
  remove_column :products, :discontinued, :boolean, default: false
end

Rename Column

def change
  rename_column :products, :upc, :sku
end

Change Column

# 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

References and Foreign Keys

Add Reference

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

Foreign Key Options

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

Indexes

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

The change Method

Auto-reversible operations (use change):

  • add_column / remove_column (with type)
  • add_foreign_key / remove_foreign_key
  • add_index / remove_index
  • add_reference / remove_reference
  • add_timestamps / remove_timestamps
  • create_table / drop_table (with block)
  • create_join_table / drop_join_table
  • rename_column
  • rename_index
  • rename_table
  • change_column_default (with :from and :to)
  • change_column_null

Reversible and Up/Down

Using reversible

def 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

Using up/down

def up
  change_column :products, :price, :decimal, precision: 12, scale: 2
end

def down
  change_column :products, :price, :decimal, precision: 10, scale: 2
end

Irreversible Migration

def up
  drop_table :legacy_products
end

def down
  raise ActiveRecord::IrreversibleMigration
end

Running Migrations

# 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

Database Commands

# 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

Safe Migration Practices

Do's

  1. Always include column type in remove_column for reversibility
  2. Use change_column_default with :from and :to
  3. Add indexes on foreign keys (automatic with references)
  4. Test rollback: rails db:migrate:redo
  5. Keep migrations small and focused

Don'ts

  1. Don't edit committed migrations - create new ones
  2. Don't use model classes directly in migrations (schema may change)
  3. Don't add data migrations - use seeds or maintenance tasks

Data Migration Alternative

# 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

Concurrent Index (PostgreSQL)

class AddIndexToUsersEmail < ActiveRecord::Migration[7.1]
  disable_ddl_transaction!

  def change
    add_index :users, :email, algorithm: :concurrently
  end
end

Additional Resources

Reference Files

  • references/migration-patterns.md - Complex migration patterns, zero-downtime migrations

Score

Total Score

65/100

Based on repository quality metrics

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

+10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

0/15
最近の活動

1ヶ月以内に更新

+10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

+5

Reviews

💬

Reviews coming soon