Episode ini membedah pengolahan teks di Ruby: encoding string dan transkoding, frozen string literal, method umum seperti split, gsub, tr, dan upcase, serta Regexp dengan capture group, operator =~, method match dan scan, dan flag i, m, x.

Sebagai developer backend, kalian akan menghabiskan banyak waktu menangani teks: memvalidasi input, mem-parsing log, mengekstrak data dari respons API, atau membersihkan string yang masuk ke database. Ruby menangani ini dengan baik berkat class String yang kaya method dan dukungan Regular Expression (regexp) kelas satu.
Episode 8 ini membedah dua topik yang saling melengkapi. Pertama, String lanjutan: encoding, frozen string literal yang menjadi default Ruby 4.0, serta method penting split, gsub, tr, dan upcase. Kedua, Regexp: cara membangun pola, capture group, operator =~, method match dan scan, serta flag i, m, dan x.
Setiap string di Ruby membawa informasi encoding — biasanya UTF-8. Memahami encoding mencegah error klasik saat membaca file atau respons dari sistem lama:
teks = "Bahasa Ruby"
puts teks.encoding
puts teks.bytesizeteks.encoding menampilkan UTF-8 dan teks.bytesize menghitung ukuran dalam byte (bukan jumlah karakter — karena karakter seperti é memakan lebih dari satu byte). Untuk mengubah encoding, gunakan encode: misalnya teks.encode("ISO-8859-1") untuk sistem lama, dan selalu encode kembali ke UTF-8 saat masuk database.
String di Ruby defaultnya mutable — bisa diubah setelah dibuat. Untuk keamanan, performa, dan konsistensi, Ruby mendukung frozen string literal via magic comment di baris pertama file. Di Ruby 4.0, perilaku ini menjadi default:
# frozen_string_literal: true
teks = "kata"
puts teks.frozen?
puts teks.upcaseteks.frozen? mengembalikan true karena literal dibekukan oleh magic comment. Method upcase (tanpa tanda seru) mengembalikan string baru tanpa mengubah aslinya. Method dengan ! seperti upcase! akan memicu FrozenError pada string beku — itulah alasan warning ruby -w di episode 7 penting dipantau.
Beberapa method string yang paling sering dipakai di production:
kalimat = "saya belajar ruby"
puts kalimat.split
puts kalimat.upcase
puts kalimat.tr("s", "z")
puts kalimat.gsub("belajar", "mempelajari")split tanpa argumen memecah string per spasi menjadi array, upcase mengubah ke huruf kapital, tr mengganti satu karakter ke karakter lain, dan gsub mengganti seluruh kemunculan pola atau substring. Versi gsub! dan tr! mengubah string aslinya; ingat perilaku ! dari episode 5.
Regexp di Ruby ditulis di antara dua garis miring: /pola/. Capture group adalah bagian pola dalam tanda kurung yang nilainya bisa diambil:
email = "kontak@example.com"
regex = /(\w+)@(\w+)\.(\w+)/
m = email.match(regex)
puts m[1]
puts m[2]
puts email =~ regexemail.match(regex) mengembalikan objek MatchData, dan m[1] mengambil capture group pertama (kontak), m[2] yang kedua (example). Operator =~ mengembalikan posisi index kemunculan pertama atau nil jika tidak cocok. Kelas \w mencocokkan huruf, angka, dan garis bawah.
Berbeda dengan match yang berhenti di kemunculan pertama, scan menemukan seluruh kemunculan pola. Ketika pola punya capture group, scan mengembalikan array berisi grup-grup tersebut:
teks = "nomor 1, nomor 2, nomor 3"
puts teks.scan(/nomor (\d)/).inspect
puts teks.scan(/\d+/).inspectteks.scan(/nomor (\d)/) menghasilkan [["1"], ["2"], ["3"]] karena ada satu capture group, sedangkan teks.scan(/\d+/) menghasilkan ["1", "2", "3"] tanpa group. inspect menampilkan representasi literal array — pasangan p yang kita pelajari di episode 3.
Regexp dan method string sering dipadukan. gsub menerima pola regexp dan string pengganti, lengkap dengan backreference \1, \2 untuk capture group:
teks = "Arman: 30 tahun"
puts teks.gsub(/(\w+): (\d+) tahun/, '\1 berusia \2')teks.gsub(/(\w+): (\d+) tahun/, '\1 berusia \2') menangkap nama dan angka, lalu menata ulang hasilnya menjadi Arman berusia 30. Block juga bisa dipakai sebagai pengganti: gsub(/pola/) { |cocok| ... } memberi kendali penuh atas hasil transformasi — pola yang umum dalam sanitasi input.
Regexp bisa diberi flag setelah garis miring penutup. Tiga yang paling penting:
i — case-insensitive: /ruby/i cocok dengan Ruby dan RUBY.m — membuat titik (.) cocok dengan newline.x — mengizinkan spasi dan komentar di dalam pola untuk keterbacaan.ruby -e 'puts "Ruby RUPY ruby".scan(/ruby/i).inspect'
ruby -e 'puts "baris satu\nbaris dua".scan(/satu.baris/m).inspect'Baris pertama memakai flag i sehingga menemukan tiga kemunculan ruby. Baris kedua memakai flag m sehingga . bisa mencocokkan karakter newline. Dalam kode panjang, flag x memungkinkan pola ditulis dengan spasi dan komentar tanpa mengubah makna — sangat membantu untuk regexp kompleks di production.
Warning
Regexp tanpa batasan bisa menjadi sumber ReDoS (Regular expression Denial of Service) jika pola menangkap input yang sangat besar. Kita akan membahas mitigasi keamanan ini di episode 15. Untuk sekarang, biasakan pola sesederhana mungkin.
Episode 8 melengkapi kalian dengan keterampilan pengolahan teks: memahami encoding UTF-8 dan transkoding, perilaku frozen string literal, method string split, gsub, tr, dan upcase, serta Regexp dengan capture group, operator =~, method match dan scan, dan flag i, m, x.
Inti yang harus dibawa pulang:
encode untuk transkoding dan bytesize untuk ukuran byte.# frozen_string_literal: true membekukan literal string; default di Ruby 4.0.! memutasi string asli; versi tanpa ! mengembalikan string baru.match mengembalikan objek MatchData; m[1] mengambil capture group.=~ mengembalikan posisi kecocokan atau nil.scan menemukan semua kemunculan; flag i case-insensitive, m dotall, x verbosity.Di episode 9 selanjutnya kita akan membahas file I/O dan data formats — membaca dan menulis file dengan File.read dan File.write, streaming file besar, class Pathname yang kini jadi core class Ruby 4.0, serta serialisasi JSON, YAML, CSV, dan Marshal untuk data biner. Persiapan penting untuk aplikasi yang berinteraksi dengan sistem file.