Çalıştırılan bir yazılım beklenmeyen sorunlar doğurabilir. Okunmaya çalışılan bir dosya mevcut olmayabilir ya da veri kaydetmemek istediğimiz disk dolu olabilir yada kullanıcı beklenmeyen bir girdi yapabilir.
ruby> file = open("bir_dosya")
ERR: (eval):1:in `open': No such file or directory - bir_dosya
Güçlü bir yazılım bu gibi durumları hassasiyetle yakalayacaktır. C yazılımcılarından, hata doğurabilecek her sistem çağrısının sonucunu kontrol etmeleri ve anında ne yapılacağına ilişkin karar vermeleri beklenir:
FILE *file = fopen("bir_dosya", "r");
if (file == NULL) {
fprintf( stderr, "Dosya mevcut değil.\n" );
exit(1);
}
bytes_read = fread( buf, 1, bytes_desired, file );
if (bytes_read != bytes_desired ) {
/* hata giderme işlemleri... */
}
...
Bu yazılımcıları dikkatsizliğe ve ihmalciliğe iten, üstelik hataları tam olarak yakalayamayan bir yazılım yazmanıza yol açan sıkıcı bir uygulamadır. Öte yandan, işi doğru düzgün yapmak, yakalanabilecek bir çok hata olduğu için yazılımın okunabilirliğini oldukça zorlaştıracaktır.
Güncel bir çok dilde olduğu gibi Ruby'de de, yazılımcıyı ya da sonradan kodumuzu okuyan kişileri sıkıntıya sokmadan, sürprizleri kod bloklarından soyutlayan bir yolla yakalayabiliriz.
begin ile işaretlenmiş kod bloğu bir istisnayla karşılaşana dek çalıştırılır, hata durumunda denetimi rescue ile işaretlenmiş kod bloğuna verir. Eğer hiçbir istisnayla karşılaşılmazsa rescue kodu kullanılmaz. Aşağıdaki yöntem bir metin dosyasının ilk satırını döndürür, bir istisna ile karşılaşırsa nil değerini:
def first_line( filename )
begin
file = open("bir_dosya")
info = file.gets
file.close
info # Değerlendirmeye alınan son şey dönüş değeri
rescue
nil # Dosyayı okuyamıyor musunuz? O zaman bir dizge dönmez.
end
end
Bir problemle yaratıcı bir biçimde ilgilenmek istediğimiz zamanlar olacaktır. Örneğin dosyaya erişmek mümkün değilse standart girdi yerine başka bir şey kullanmak isteyebiliriz:
begin
file = open("bir_dosya")
rescue
file = STDIN
end
begin
# ... girdiyi değerlendir ...
rescue
# ... burada diğer istisnalarla uğraş.
end
begin kodunu tekrar çalıştırmak için rescue'nun içinde retry'ı kullanabiliriz. Bu bize önceki örneğimizi daha kısa şekilde yazmamıza izin verir:
fname = "bir_dosya"
begin
file = open(fname)
# ... girdiyi degerlendir ...
rescue
fname = "STDIN"
retry
end
Ancak burada bir kusur bulunmaktadır. Hiç olmayan bir dosya bu kodun sonsuz bir döngüde kendisini tekrar etmesini sağlayacaktır. retry'ı kullanırken bu tür durumlara dikkat etmelisiniz.
Her Ruby kütüphanesi, sizin de kendi kodunuzda yapabileceğiniz gibi, herhangi bir hata karşısında bir istisna doğurur. Bir istisnayı çıkarmak için raise kullanılır. raise tek argüman olarak istisnayı açıklayan bir dizge alır. Bu argüman isteğe bağlıdır ancak atlanmaması gereken bir husustur. Özel değişkenlerden olan $! ile sonradan ulaşılabilir.
ruby> raise "deneme hatası"
deneme hatası
ruby> begin
| raise "dnm2"
| rescue
| print "Bir hata meydana geldi: ",$!, "\n"
| end
Bir hata meydana geldi: dnm2
nil