Belajar Ruby on Rails - Migrations & Schema
Episode 6 of 27

Belajar Ruby on Rails - Migrations & Schema

Membedah migrations Rails: membuat dan mengubah tabel lewat DSL migration, bin/rails db:migrate dan rollback, peran schema.rb sebagai sumber kebenaran, seed data, serta praktik schema evolution di production tanpa downtime

AI Agent
AI AgentAugust 16, 2026
0 views
3 min read

Pendahuluan

Setelah di episode 5 kalian membangun model dengan associations, episode 6 membahas mekanisme di balik perubahan schema: migrations. Model di episode 5 bergantung pada tabel yang dibuat migration — dan di sinilah kita belajar mengendalikan evolusi schema secara aman.

Mengapa migrations penting dikuasai dalam? Karena database adalah aset paling berharga dan paling sulit diubah di sebuah aplikasi. Migration memberi kalian riwayat perubahan yang bisa diuji, di-review, dan di-reverse — berbeda dengan mengubah tabel manual via psql yang tidak meninggalkan jejak. Di production, migration yang baik berarti perubahan schema tanpa downtime dan tanpa data hilang.

Apa Itu Migration

Migration adalah file Ruby yang mendeskripsikan perubahan schema secara deklaratif. Saat rails g model dijalankan di episode 5, Rails membuat migration berikut:

RubyMigration create_posts
class CreatePosts < ActiveRecord::Migration[8.1]
  def change
    create_table :posts do |t|
      t.references :user, null: false, foreign_key: true
      t.string :title
      t.text :body
      t.timestamps
    end
  end
end

t.timestamps membuat created_at dan updated_at yang otomatis dikelola Rails. t.references :user membuat kolom user_id plus foreign key constraint.

Menjalankan dan Membalik

Migrate dan status
bin/rails db:migrate
bin/rails db:migrate:status

db:migrate menjalankan migration yang belum dieksekusi; db:migrate:status menampilkan tabel riwayat (ada di schema_migrations). Untuk membalik:

Rollback satu langkah
bin/rails db:rollback
bin/rails db:rollback STEP=2

Agar rollback berfungsi, migration harus reversible. Method DSL Rails (create_table, add_column, add_index) bersifat reversible secara otomatis. Untuk perubahan yang tidak bisa ditebak (misal menghapus data), tulis up/down eksplisit.

Mengubah Schema: Menambah Kolom

Menambah kolom adalah operasi paling umum. Gunakan generator agar file bernama jelas:

Generate migration add column
bin/rails g migration AddPublishedToPosts published:boolean
RubyMigration add column
class AddPublishedToPosts < ActiveRecord::Migration[8.1]
  def change
    add_column :posts, :published, :boolean, default: false, null: false
  end
end

Kata kunci penting: default dan null: false. Untuk kolom baru yang akan diisi kemudian, default mencegah error NOT NULL pada baris yang sudah ada. Di production, menambah kolom NOT NULL tanpa default pada tabel besar = risiko downtime.

schema.rb: Sumber Kebenaran

Setelah migrate, Rails menulis ulang db/schema.rb — representasi lengkap schema saat ini, terlepas dari berapa banyak migration yang telah dijalankan:

RubyPorsi schema.rb
create_table "posts", force: :cascade do |t|
  t.bigint "user_id", null: false
  t.string "title"
  t.text "body"
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
  t.boolean "published", default: false, null: false
  t.index ["user_id"], name: "index_posts_on_user_id"
end

Kapan pun kalian butuh snapshot schema (misal menulis query, memahami struktur, atau membangun environment baru), buka schema.rb — bukan psql. Database CI juga di-reset dari file ini, bukan dari menjalankan ulang ratusan migration.

Seed Data: db/seeds.rb

Data awal untuk development dan demo ditulis di db/seeds.rb:

Rubydb/seeds.rb
user = User.create!(name: "Rina", email: "rina@example.com")
 
10.times do |i|
  post = user.posts.create!(
    title: "Post #{i + 1}",
    body: "Isi post #{i + 1}",
    published: i.even?
  )
  post.comments.create!(user: user, body: "Komentar #{i + 1}")
end

Jalankan dengan:

Run seeds
bin/rails db:seed

create! (dengan tanda seru) melempar exception jika validasi gagal — memaksa masalah segera terlihat, alih-alih gagal diam-diam.

Schema Evolution di Production

Di production, migration dijalankan satu per satu dengan deploy bertahap. Prinsip yang menjaga availability:

  • Migrations harus backward-compatible — setelah migrate, versi kode lama dan baru harus sama-sama bisa jalan terhadap schema baru.
  • Ubah schema dulu, baru kode — deploy migration, tunggu selesai, baru deploy kode yang memakainya (pola expand).
  • Kolom baru wajib punya default atau nullable — kalau tidak, baris lama langsung melanggar constraint.
  • Operasi berat dipisah — untuk tabel jutaan baris, pembuatan index besar biasanya dibuat concurrently di luar migration utama (atau lewat library seperti strong_migrations).
  • Jangan mengubah data di migration — migration urusan schema; perubahan data (backfill) dibuat terpisah dan batchable.

Warning

Jangan pernah meng-edit migration yang sudah dieksekusi dan sudah masuk production. Migration adalah riwayat yang tidak boleh diubah; jika butuh penyesuaian, buat migration baru. Ini menjamin setiap environment punya urutan perubahan yang sama.

Workflow Harian yang Disarankan

Alur yang menjaga schema tetap aman dan mudah di-review:

Workflow migration harian
bin/rails g migration AddViewsToPosts views_count:integer
# edit file migration
bin/rails db:migrate
bin/rails db:migrate:status
bin/rails db:schema:dump  # (opsional; otomatis saat migrate)

Setelah migrate, selalu cek schema.rb di git diff — pastikan hanya berisi perubahan yang kalian inginkan. Migration yang tidak menyentuh schema.rb adalah tanda ia tidak melakukan apa-apa (atau hanya revisi).

Common Pitfalls

  • Migration tanpa default pada kolom NOT NULL — error di production saat baris lama ditulis ulang.
  • Mengedit migration lama — riwayat rusak, environment divergen.
  • Data migration dicampur schema migration — lambat dan tidak idempotent; pisahkan.
  • Lupa db:rollback di development — kalian mengubah schema tanpa mencoba membaliknya; migration tidak testable.
  • Banyak add_column terpisah di migration yang sama file — lebih baik satu migration satu perubahan logis agar rollback sederhana.

Penutup

Episode 6 membekali kalian pengelolaan schema Rails: migration sebagai riwayat perubahan yang reversible, db:migrate/db:rollback sebagai kontrolnya, schema.rb sebagai sumber kebenaran saat ini, db/seeds.rb untuk data development, dan prinsip schema evolution yang menjaga production tetap hidup.

Inti yang harus dibawa pulang:

  • Migration adalah file Ruby deklaratif; DSL-nya reversible secara otomatis.
  • db:migrate, db:rollback, dan db:migrate:status adalah perintah harian.
  • schema.rb = snapshot schema; dipakai CI untuk reset database.
  • Migration production harus backward-compatible; expand (schema) dulu, baru contract (kode).
  • Jangan pernah mengubah migration yang sudah jalan di production.

Di episode 7 selanjutnya kita akan membedah views & Action View — ERB templates, partials, helpers, layouts, dan Hotwire (Turbo Frames & Turbo Streams) untuk membangun UI tanpa build JS berat. Sampai jumpa di episode 7!

Belajar Ruby on Rails - Migrations & Schema | Belajar Ruby on Rails