Sintaks Utama

Sintaks Utama #

Ruby dirancang dengan satu filosofi utama: kode yang ditulis harus mudah dibaca oleh manusia, bukan hanya oleh mesin. Hasilnya adalah bahasa yang sintaksnya sangat ekspresif — kamu bisa menulis kode yang hampir terasa seperti membaca kalimat dalam bahasa Inggris. Tapi ekspresivitas ini bukan berarti tidak ada aturan. Ruby punya konvensi yang cukup ketat tentang bagaimana kode seharusnya ditulis, dan memahami konvensi ini sejak awal adalah kunci untuk menulis Ruby yang idiomatik. Artikel ini membahas semua fondasi sintaks Ruby — dari variabel hingga error handling — dengan penekanan pada cara penulisan yang dianggap benar oleh komunitas Ruby.

Variabel dan Ruang Lingkup #

Salah satu hal pertama yang membuat Ruby berbeda dari banyak bahasa lain adalah cara menandai jenis variabel menggunakan prefix tertentu. Tidak ada deklarasi tipe seperti int atau string — tapi Ruby punya cara sendiri untuk membedakan di mana sebuah variabel bisa diakses.

flowchart TD
    A[Variabel Ruby] --> B["Tanpa prefix\nVariabel Lokal"]
    A --> C["@prefix\nVariabel Instance"]
    A --> D["@@prefix\nVariabel Kelas"]
    A --> E["$prefix\nVariabel Global"]
    B --> B1["Hanya dalam\nmetode/blok saat ini"]
    C --> C1["Dalam seluruh\ninstance objek"]
    D --> D1["Berbagi di semua\ninstance kelas"]
    E --> E1["Di mana saja\ndalam program"]

Variabel Lokal #

Variabel lokal dimulai dengan huruf kecil atau underscore (_). Ruang lingkupnya terbatas pada blok kode tempat ia didefinisikan — jika kamu definisikan di dalam sebuah metode, variabel itu tidak bisa diakses dari metode lain.

def hitung_total(harga, jumlah)
  diskon = 0.1                    # variabel lokal
  subtotal = harga * jumlah       # variabel lokal
  total = subtotal - (subtotal * diskon)
  total
end

# ANTI-PATTERN: mencoba akses variabel lokal dari luar scope-nya
puts diskon   # => NameError: undefined local variable or method 'diskon'

# BENAR: variabel lokal hanya hidup di dalam metodenya
puts hitung_total(100_000, 3)   # => 270000.0

Konvensi penamaan variabel lokal di Ruby menggunakan snake_case — semua huruf kecil dengan underscore sebagai pemisah kata. Ini bukan sekadar gaya; komunitas Ruby menganggap camelCase untuk variabel lokal sebagai kode yang tidak idiomatik.

# ANTI-PATTERN: camelCase untuk variabel lokal
firstName = "Budi"
totalHarga = 50_000

# BENAR: snake_case
first_name = "Budi"
total_harga = 50_000

Variabel Instance #

Variabel instance diawali dengan @ dan hidup selama objek dari kelas tersebut hidup. Semua metode dalam satu instance bisa mengaksesnya, tapi instance yang berbeda punya nilai @ yang berbeda pula.

class Mahasiswa
  def initialize(nama, nim)
    @nama = nama    # variabel instance
    @nim  = nim     # variabel instance
  end

  def perkenalan
    # @nama bisa diakses di sini karena masih instance yang sama
    "Halo, saya #{@nama} dengan NIM #{@nim}."
  end

  def ubah_nama(nama_baru)
    @nama = nama_baru
  end
end

mhs1 = Mahasiswa.new("Rina", "20230001")
mhs2 = Mahasiswa.new("Bagas", "20230002")

puts mhs1.perkenalan  # => Halo, saya Rina dengan NIM 20230001.
puts mhs2.perkenalan  # => Halo, saya Bagas dengan NIM 20230002.

mhs1.ubah_nama("Rina Wijaya")
puts mhs1.perkenalan  # => Halo, saya Rina Wijaya dengan NIM 20230001.
puts mhs2.perkenalan  # => Halo, saya Bagas dengan NIM 20230002. (tidak terpengaruh)

Variabel Kelas #

Variabel kelas diawali dengan @@ dan berbagi nilai di semua instance dari kelas yang sama. Ini berguna untuk melacak state yang berlaku untuk seluruh kelas, bukan per-objek.

class Koneksi
  @@jumlah_koneksi = 0   # variabel kelas, berbagi di semua instance

  def initialize(host)
    @host = host
    @@jumlah_koneksi += 1
  end

  def self.jumlah_aktif
    @@jumlah_koneksi
  end
end

k1 = Koneksi.new("db-primary")
k2 = Koneksi.new("db-replica")
k3 = Koneksi.new("cache")

puts Koneksi.jumlah_aktif   # => 3
Variabel kelas (@@) terwarisi oleh subkelas dan bisa menyebabkan bug yang sulit dilacak. Jika sebuah subkelas mengubah nilai @@, perubahan itu juga terlihat di kelas induk. Dalam kode modern, banyak developer Ruby lebih memilih menggunakan variabel instance di level kelas (@variable di dalam self.method) daripada @@variable untuk menghindari masalah ini.

Variabel Global #

Variabel global diawali dengan $ dan bisa diakses dari mana saja dalam program. Ini terdengar praktis, tapi hampir selalu merupakan pilihan yang buruk.

# ANTI-PATTERN: variabel global membuat kode sulit diprediksi
$mode_debug = true

def proses_data(data)
  puts "[DEBUG] Memproses: #{data}" if $mode_debug
  # kode lain...
end

# BENAR: gunakan parameter atau konstanta sebagai alternatif
DEBUG_MODE = ENV["DEBUG"] == "true"   # baca dari environment

def proses_data(data, verbose: false)
  puts "[DEBUG] Memproses: #{data}" if verbose
  # kode lain...
end
Kapan variabel global bisa diterima:
  ✓ Variabel built-in Ruby seperti $stdin, $stdout, $stderr
  ✓ $0 untuk nama file program yang sedang berjalan
  ✓ $LOAD_PATH untuk jalur pencarian library
  ✗ Variabel global buatan sendiri untuk menyimpan state aplikasi
  ✗ Sebagai "shortcut" karena malas melewatkan parameter

Tipe Data #

Ruby bersifat dynamically typed — kamu tidak perlu mendeklarasikan tipe variabel. Tapi setiap nilai di Ruby adalah objek, dan setiap objek punya tipenya sendiri. Memahami tipe data dasar Ruby adalah fondasi yang tidak bisa dilewati.

String #

String di Ruby bisa ditulis dengan tanda kutip tunggal (') atau ganda ("). Perbedaannya bukan sekadar kosmetik.

nama   = "Dewi"
kota   = 'Jakarta'

# Kutip ganda: mendukung string interpolation dan escape sequence
puts "Halo, #{nama}! Kamu dari #{kota}."   # => Halo, Dewi! Kamu dari Jakarta.
puts "Baris baru:\nIni baris kedua."       # => newline aktif

# Kutip tunggal: literal, tidak ada interpolasi atau escape
puts 'Halo, #{nama}!'     # => Halo, #{nama}!  (dicetak apa adanya)
puts 'Baris baru:\n...'   # => Baris baru:\n...  (\n tidak diproses)
# ANTI-PATTERN: string concatenation dengan +
pesan = "Selamat datang, " + nama + "! Kamu dari " + kota + "."

# BENAR: gunakan interpolasi — lebih bersih dan lebih cepat
pesan = "Selamat datang, #{nama}! Kamu dari #{kota}."

Beberapa method String yang sering dipakai:

teks = "  Ruby adalah bahasa yang menyenangkan!  "

teks.strip          # => "Ruby adalah bahasa yang menyenangkan!"
teks.upcase         # => "  RUBY ADALAH BAHASA YANG MENYENANGKAN!  "
teks.downcase       # => "  ruby adalah bahasa yang menyenangkan!  "
teks.include?("Ruby")  # => true
teks.split(" ")     # => ["Ruby", "adalah", "bahasa", "yang", "menyenangkan!"]
teks.gsub("Ruby", "Python")  # => "  Python adalah bahasa yang menyenangkan!  "

Integer dan Float #

Ruby membedakan bilangan bulat (Integer) dan bilangan desimal (Float). Operasi antara dua Integer menghasilkan Integer — termasuk pembagian.

# ANTI-PATTERN: pembagian integer menghasilkan hasil yang mengejutkan
puts 7 / 2     # => 3  (bukan 3.5!)
puts 7 % 2     # => 1  (sisa bagi)

# BENAR: gunakan Float jika butuh hasil desimal
puts 7.0 / 2   # => 3.5
puts 7 / 2.0   # => 3.5
puts 7.fdiv(2) # => 3.5  (cara idiomatik Ruby)

Ruby mendukung underscore sebagai pemisah ribuan untuk keterbacaan:

populasi_indonesia = 270_000_000   # jauh lebih mudah dibaca dari 270000000
harga_rumah = 1_500_000_000
pi_approx   = 3.141_592_653

Symbol #

Symbol adalah tipe data yang sering membingungkan pemula. Symbol mirip String tapi tidak sama — Symbol adalah identifier yang tidak berubah (immutable) dan selalu merujuk ke objek yang sama di memori.

# Symbol: dimulai dengan titik dua
status = :aktif
role   = :admin

# ANTI-PATTERN: menggunakan string sebagai key hash
user = {"nama" => "Andi", "role" => "admin"}

# BENAR: gunakan symbol sebagai key hash — lebih efisien
user = {nama: "Andi", role: :admin}
puts user[:nama]   # => Andi
# Symbol adalah singleton — objek yang sama di memori
puts :aktif.object_id == :aktif.object_id  # => true
puts "aktif".object_id == "aktif".object_id  # => false (dua objek berbeda)

Array #

Array adalah koleksi terurut yang bisa menampung objek dari tipe apapun.

# Membuat array
buah  = ["apel", "mangga", "jeruk"]
angka = [1, 2, 3, 4, 5]
campur = [1, "dua", :tiga, 4.0, true]

# Akses elemen
puts buah[0]     # => apel
puts buah[-1]    # => jeruk  (indeks negatif dari belakang)
puts buah[1..2]  # => ["mangga", "jeruk"]  (range)

# Method umum
buah.push("nanas")         # tambah di belakang
buah.unshift("durian")     # tambah di depan
buah.pop                   # hapus dan kembalikan elemen terakhir
buah.length                # => jumlah elemen

# Iterasi — cara idiomatik Ruby
buah.each { |b| puts b }
buah.map  { |b| b.upcase }    # => ["APEL", "MANGGA", "JERUK"]
buah.select { |b| b.length > 4 }  # => ["mangga", "jeruk"]
buah.reject { |b| b.start_with?("a") }  # => ["mangga", "jeruk"]

Hash #

Hash adalah koleksi pasangan kunci-nilai, mirip dictionary di Python atau object di JavaScript.

# Hash dengan symbol key (cara modern)
profil = {
  nama:  "Siti",
  umur:  28,
  kota:  "Bandung",
  aktif: true
}

puts profil[:nama]   # => Siti
puts profil[:umur]   # => 28

# Tambah atau ubah key
profil[:email] = "[email protected]"
profil[:umur]  = 29

# Cek keberadaan key
profil.key?(:email)    # => true
profil.key?(:telepon)  # => false

# Iterasi
profil.each do |kunci, nilai|
  puts "#{kunci}: #{nilai}"
end

# Transformasi
profil.map { |k, v| [k, v.to_s] }.to_h   # semua nilai jadi string
profil.select { |k, v| v.is_a?(String) }  # hanya nilai bertipe String

Operator #

Ruby mendukung semua operator standar, ditambah beberapa operator unik yang membuatnya sangat ekspresif.

Operator Aritmatika dan Perbandingan #

# Aritmatika
puts 10 + 3   # => 13
puts 10 - 3   # => 7
puts 10 * 3   # => 30
puts 10 / 3   # => 3   (integer division)
puts 10 % 3   # => 1   (modulo)
puts 10 ** 3  # => 1000 (pangkat)

# Perbandingan
puts 10 > 3    # => true
puts 10 < 3    # => false
puts 10 >= 10  # => true
puts 10 == 10  # => true
puts 10 != 3   # => true

Spaceship Operator (<=>) #

Ruby punya operator unik yang disebut spaceship operator — sangat berguna untuk sorting.

puts 1 <=> 2    # => -1  (kiri lebih kecil)
puts 2 <=> 2    # => 0   (sama)
puts 3 <=> 2    # => 1   (kiri lebih besar)

# Penggunaan praktis: sort dengan aturan kustom
nama = ["Citra", "Andi", "Bagas", "Devi"]
nama.sort { |a, b| a <=> b }  # => ["Andi", "Bagas", "Citra", "Devi"]
nama.sort { |a, b| b <=> a }  # => ["Devi", "Citra", "Bagas", "Andi"] (terbalik)

Safe Navigation Operator (&.) #

Operator &. (disebut lonely operator) mencegah NoMethodError saat memanggil method pada nilai yang mungkin nil.

# ANTI-PATTERN: rentan NoMethodError jika user nil
def tampilkan_email(user)
  puts user.email.upcase
end

# BENAR: gunakan safe navigation operator
def tampilkan_email(user)
  puts user&.email&.upcase || "Email tidak tersedia"
end

Operator Logika #

# && dan || (lebih ketat, direkomendasikan untuk kondisi)
puts true && false   # => false
puts true || false   # => true
puts !true           # => false

# and, or, not (lebih longgar, hindari dalam ekspresi kondisi)
# Gunakan 'and' dan 'or' hanya untuk flow control, bukan ekspresi boolean

# ANTI-PATTERN: and/or dalam kondisi bisa mengejutkan
nilai = true and false   # nilai = true (bukan false!)
nilai = true && false    # nilai = false (seperti yang diharapkan)

Kontrol Alur #

Ruby memberikan banyak cara untuk mengontrol alur program. Yang membedakan Ruby adalah banyak dari konstruk ini bisa ditulis dalam bentuk yang sangat ringkas.

Kondisional #

nilai = 75

# Bentuk standar
if nilai >= 80
  puts "Lulus dengan nilai bagus"
elsif nilai >= 60
  puts "Lulus"
else
  puts "Tidak lulus"
end

# Inline if — untuk kondisi sederhana satu baris
puts "Lulus" if nilai >= 60
puts "Tidak lulus" unless nilai >= 60   # unless = if not

# Ternary — untuk assignment kondisional
status = nilai >= 60 ? "Lulus" : "Tidak lulus"
# ANTI-PATTERN: ternary bertumpuk — sulit dibaca
hasil = a > b ? (a > c ? a : c) : (b > c ? b : c)

# BENAR: gunakan if-elsif untuk kondisi bertumpuk
hasil = if a > b && a > c
           a
         elsif b > c
           b
         else
           c
         end

Case/When #

case di Ruby jauh lebih powerful dari switch di bahasa lain — ia bisa mencocokkan berdasarkan kelas, range, regex, dan bahkan kondisi kustom.

nilai = 85

# Matching dengan range
grade = case nilai
        when 90..100 then "A"
        when 80..89  then "B"
        when 70..79  then "C"
        when 60..69  then "D"
        else              "E"
        end
puts grade   # => B

# Matching dengan kelas
def deskripsikan(objek)
  case objek
  when String  then "Ini adalah String: #{objek}"
  when Integer then "Ini adalah Integer: #{objek}"
  when Array   then "Ini adalah Array dengan #{objek.length} elemen"
  when NilClass then "Ini adalah nil"
  else "Tipe tidak dikenal: #{objek.class}"
  end
end

puts deskripsikan("Ruby")    # => Ini adalah String: Ruby
puts deskripsikan(42)        # => Ini adalah Integer: 42
puts deskripsikan([1, 2, 3]) # => Ini adalah Array dengan 3 elemen

Perulangan #

Ruby punya banyak cara untuk melakukan perulangan. Yang paling idiomatik adalah menggunakan iterator dari Enumerable, bukan for atau while.

# ANTI-PATTERN: menggunakan for loop ala C
for i in 0..4
  puts i
end

# BENAR: gunakan .each atau .times
5.times { |i| puts i }
(0..4).each { |i| puts i }

# Iterasi array
produk = ["laptop", "mouse", "keyboard"]

# ANTI-PATTERN: akses via indeks manual
i = 0
while i < produk.length
  puts produk[i]
  i += 1
end

# BENAR: each
produk.each { |p| puts p }

# Jika butuh indeks sekaligus nilai:
produk.each_with_index do |p, i|
  puts "#{i + 1}. #{p}"
end
# => 1. laptop
# => 2. mouse
# => 3. keyboard
# Loop dengan while dan until
hitung = 0
while hitung < 5
  hitung += 1
end

hitung = 0
until hitung == 5
  hitung += 1
end

# loop dengan break — untuk loop tak terbatas
loop do
  input = gets.chomp
  break if input == "keluar"
  puts "Kamu ketik: #{input}"
end

Blok, Proc, dan Lambda #

Blok, Proc, dan Lambda adalah tiga cara Ruby merepresentasikan potongan kode yang bisa diteruskan dan dipanggil belakangan. Memahami perbedaannya adalah salah satu bagian terpenting dalam belajar Ruby.

flowchart TD
    A[Potongan Kode yang Bisa Diteruskan] --> B[Blok]
    A --> C[Proc]
    A --> D[Lambda]
    B --> B1["Tidak bisa disimpan\nke variabel"]
    B --> B2["Diteruskan langsung\nke metode"]
    C --> C1["Bisa disimpan\nke variabel"]
    C --> C2["Return keluar dari\nmetode yang memanggilnya"]
    D --> D1["Bisa disimpan\nke variabel"]
    D --> D2["Return hanya keluar\ndari lambda itu sendiri"]
    D --> D3["Cek jumlah\nargumen secara ketat"]

Blok #

Blok adalah segmen kode yang diteruskan ke metode. Blok tidak bisa disimpan ke variabel — ia hanya bisa digunakan langsung saat memanggil metode.

# Sintaks blok: do...end atau { }
# Gunakan do...end untuk blok multi-baris:
[1, 2, 3].each do |n|
  kuadrat = n ** 2
  puts "#{n}^2 = #{kuadrat}"
end

# Gunakan { } untuk blok satu baris:
[1, 2, 3].map { |n| n ** 2 }   # => [1, 4, 9]

# Membuat metode yang menerima blok:
def jalankan_dua_kali
  yield   # panggil blok yang diteruskan
  yield
end

jalankan_dua_kali { puts "Halo!" }
# => Halo!
# => Halo!

# Meneruskan nilai ke blok via yield:
def sapa(nama)
  yield nama if block_given?
end

sapa("Dewi") { |n| puts "Selamat datang, #{n}!" }
# => Selamat datang, Dewi!

Proc #

Proc adalah blok yang disimpan sebagai objek. Ini berguna ketika kamu ingin menyimpan logika yang sama untuk digunakan berkali-kali.

validasi_positif = Proc.new { |n| n > 0 }

puts validasi_positif.call(5)    # => true
puts validasi_positif.call(-3)   # => false

# Proc bisa diteruskan ke metode dengan &
angka = [-2, -1, 0, 1, 2, 3]
positif = angka.select(&validasi_positif)
puts positif.inspect   # => [1, 2, 3]
# PENTING: return di dalam Proc keluar dari metode yang memanggilnya
def cek_nilai
  validasi = Proc.new { return "keluar dari metode" }
  validasi.call
  puts "Baris ini tidak akan dieksekusi"  # tidak pernah sampai sini
end

puts cek_nilai   # => keluar dari metode

Lambda #

Lambda adalah Proc dengan dua perbedaan penting: ia memeriksa jumlah argumen secara ketat, dan return di dalam Lambda hanya keluar dari Lambda itu sendiri (bukan dari metode pemanggil).

# Sintaks lambda
kalikan = ->(a, b) { a * b }
sapa    = lambda { |nama| "Halo, #{nama}!" }

puts kalikan.call(4, 5)   # => 20
puts sapa.call("Rudi")    # => Halo, Rudi!

# Lambda ketat soal argumen
kalikan.call(4)       # => ArgumentError: wrong number of arguments (given 1, expected 2)

# BENAR: return dari lambda tidak keluar dari metode
def cek_lambda
  hitung = ->(n) { return n * 2 }
  hasil = hitung.call(10)
  puts "Hasil: #{hasil}"  # baris ini TETAP dieksekusi
end

cek_lambda   # => Hasil: 20
BlokProcLambda
Simpan ke variabel
Cek jumlah argumenTidakTidakYa (ketat)
Perilaku returnKeluar dari metodeKeluar dari metodeKeluar dari lambda
Cara buatdo..end / {}Proc.new {}-> {} / lambda {}

Metode Khusus #

Ruby punya beberapa metode dan keyword khusus yang perlu dipahami untuk menulis kelas yang baik.

attr_reader, attr_writer, attr_accessor #

Daripada menulis getter dan setter secara manual, Ruby menyediakan shortcut melalui attr_*.

# ANTI-PATTERN: getter dan setter manual yang verbose
class Produk
  def nama
    @nama
  end

  def nama=(nilai)
    @nama = nilai
  end

  def harga
    @harga
  end
end

# BENAR: gunakan attr_accessor
class Produk
  attr_reader   :id       # hanya bisa dibaca
  attr_writer   :stok     # hanya bisa diubah
  attr_accessor :nama, :harga  # bisa dibaca dan diubah

  def initialize(id, nama, harga)
    @id    = id
    @nama  = nama
    @harga = harga
    @stok  = 0
  end

  def info
    "#{@nama} - Rp #{@harga}"
  end
end

p = Produk.new(1, "Keyboard", 350_000)
puts p.nama    # => Keyboard
puts p.harga   # => 350000
p.nama = "Mechanical Keyboard"
p.harga = 500_000
puts p.info    # => Mechanical Keyboard - Rp 500000

Method dengan Default dan Keyword Arguments #

# Default argument
def kirim_email(tujuan, subjek = "Tanpa Subjek", format = :html)
  puts "Kirim ke #{tujuan} | Subjek: #{subjek} | Format: #{format}"
end

kirim_email("[email protected]")
kirim_email("[email protected]", "Selamat Datang")

# Keyword argument — lebih eksplisit dan urutan tidak penting
def buat_user(nama:, email:, role: :user, aktif: true)
  puts "User: #{nama} (#{email}) | Role: #{role} | Aktif: #{aktif}"
end

buat_user(nama: "Rina", email: "[email protected]")
buat_user(email: "[email protected]", nama: "Admin", role: :admin)

Error Handling #

Ruby menggunakan mekanisme begin...rescue...ensure untuk menangani exception. Memahami cara yang benar untuk menangani error adalah perbedaan antara kode yang rapuh dan kode yang tangguh.

sequenceDiagram
    participant Program
    participant Begin as begin block
    participant Rescue as rescue block
    participant Ensure as ensure block

    Program->>Begin: Jalankan kode
    alt Tidak ada error
        Begin-->>Ensure: Selesai normal
    else Ada error
        Begin->>Rescue: Lempar exception
        Rescue-->>Ensure: Tangani error
    end
    Ensure-->>Program: Selalu dijalankan
def bagi(a, b)
  begin
    hasil = a / b
    puts "Hasil: #{hasil}"
  rescue ZeroDivisionError => e
    puts "Error: tidak bisa membagi dengan nol — #{e.message}"
  rescue TypeError => e
    puts "Error: tipe data salah — #{e.message}"
  ensure
    puts "Operasi selesai."  # selalu dijalankan
  end
end

bagi(10, 2)    # => Hasil: 5 \n Operasi selesai.
bagi(10, 0)    # => Error: tidak bisa membagi dengan nol... \n Operasi selesai.
bagi(10, "a")  # => Error: tipe data salah... \n Operasi selesai.
# ANTI-PATTERN: menangkap semua exception sekaligus tanpa tahu jenisnya
begin
  # kode berisiko
rescue Exception => e
  puts "Ada error: #{e}"  # terlalu lebar — akan menangkap bahkan Ctrl+C!
end

# BENAR: tangkap exception yang spesifik
begin
  # kode berisiko
rescue ActiveRecord::RecordNotFound => e
  # tangani record tidak ditemukan
rescue Net::TimeoutError => e
  # tangani timeout
rescue StandardError => e
  # fallback untuk error umum
end
# Raise exception sendiri
def validasi_umur(umur)
  raise ArgumentError, "Umur tidak boleh negatif" if umur < 0
  raise ArgumentError, "Umur tidak realistis" if umur > 150
  umur
end

begin
  validasi_umur(-5)
rescue ArgumentError => e
  puts "Validasi gagal: #{e.message}"  # => Validasi gagal: Umur tidak boleh negatif
end

# retry — coba ulang setelah error
percobaan = 0
begin
  percobaan += 1
  puts "Percobaan ke-#{percobaan}"
  raise "Koneksi gagal" if percobaan < 3
  puts "Berhasil!"
rescue RuntimeError => e
  retry if percobaan < 3
  puts "Menyerah setelah 3 percobaan: #{e.message}"
end

Ringkasan #

  • Prefix variabel menentukan scope — tanpa prefix (lokal), @ (instance), @@ (kelas), $ (global). Hindari variabel global buatan sendiri.
  • snake_case untuk segalanya — variabel, metode, dan file Ruby menggunakan snake_case, bukan camelCase.
  • Symbol untuk key hash — lebih efisien dari String karena merupakan singleton di memori.
  • Interpolasi, bukan konkatenasi"Halo, #{nama}" lebih bersih dan lebih cepat dari "Halo, " + nama.
  • Iterator Enumerable lebih idiomatik dari for — gunakan .each, .map, .select, .reject daripada for loop.
  • Lambda lebih aman dari Proc — Lambda memeriksa argumen secara ketat dan return-nya tidak bocor ke metode pemanggil.
  • Tangkap exception yang spesifik — jangan pernah rescue Exception secara mentah; pilih kelas exception yang sesuai.
  • attr_accessor menghemat boilerplate — gunakan attr_reader, attr_writer, atau attr_accessor daripada menulis getter/setter manual.
  • Safe navigation &. mencegah NoMethodError — gunakan ketika memanggil method pada nilai yang mungkin nil.

← Sebelumnya: Instalasi   Berikutnya: Komentar →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact