Introduction
Migrations are Ruby classes that let you modify your database schema over time. They provide version control for your database, so your entire team stays in sync and changes can be rolled back safely.
Key Concepts
- Migration: A Ruby class that defines a set of reversible database schema changes.
- Schema file (
db/schema.rb): An auto-generated snapshot of your current database structure. - Column types: Rails supports
:string,:text,:integer,:boolean,:datetime,:decimal,:json, and more. - Timestamps:
t.timestampsaddscreated_atandupdated_atcolumns automatically.
Real World Context
In a team environment, you cannot just edit the database directly. Migrations let each developer apply the same schema changes in order. They are committed to version control, so deploying to production is just running bin/rails db:migrate.
Deep Dive
Creating Migrations
bash# Generate a migration bin/rails generate migration AddPublishedToArticles published:boolean
rubyclass AddPublishedToArticles < ActiveRecord::Migration[8.1] def change add_column :articles, :published, :boolean, default: false end end
Common Migration Methods
ruby# Create a table create_table :products do |t| t.string :name, null: false t.decimal :price, precision: 10, scale: 2 t.boolean :active, default: true t.references :category, foreign_key: true t.timestamps end # Modify columns add_column :articles, :published_at, :datetime remove_column :articles, :author_name, :string rename_column :articles, :title, :headline add_index :users, :email, unique: true
Running Migrations
bashbin/rails db:migrate # Run pending migrations bin/rails db:rollback # Undo last migration bin/rails db:rollback STEP=3 # Undo last 3 bin/rails db:migrate:status # Check status
The Schema File
rubyActiveRecord::Schema[8.1].define(version: 2024_01_01_120000) do create_table "articles", force: :cascade do |t| t.string "title" t.text "body" t.boolean "published", default: false t.datetime "created_at", null: false t.datetime "updated_at", null: false end end
Common Pitfalls
- Editing
db/schema.rbdirectly: This file is auto-generated. Always use migrations to change the schema. - Non-reversible migrations: Use
changemethod instead of separateup/downmethods when possible, so Rails can auto-reverse. - Forgetting indexes on foreign keys: Always add indexes on columns used in
WHEREclauses and foreign keys.
Best Practices
- Run
bin/rails db:migrateimmediately after creating a migration. - Never edit a migration that has already been run in production; create a new one instead.
- Use
null: falseanddefault:values to enforce data integrity at the database level.
Summary
- Migrations version-control your database schema using Ruby instead of raw SQL.
- Use generators to create migrations:
bin/rails generate migration Name. - Common methods:
create_table,add_column,remove_column,add_index. - Run with
bin/rails db:migrate, roll back withbin/rails db:rollback. - The schema file (
db/schema.rb) is auto-generated and should not be edited manually.
Code Examples
ruby
class CreateProducts < ActiveRecord::Migration[8.1]
def change
create_table :products do |t|
t.string :name, null: false
t.decimal :price, precision: 10, scale: 2
t.boolean :active, default: true
t.references :category, foreign_key: true
t.timestamps
end
end
end