• בלוג
  • זהירות: תפיסת חריג מבלוק ברובי

זהירות: תפיסת חריג מבלוק ברובי

03/04/2026

הקוד הבא ברובי זורק Exception מתוך הלולאה ותופס אותה, וקל לראות שזה עובד:

begin
  [1, 2, 3].each do |i|
    raise 'Stop' if i.even?
  end
rescue => e
  puts "Error: #{e.message}"
end

אבל חשוב לא להתבלבל, המבנה של rescue אחרי בלוק לא מבטיח שכל Exception שייזרק מהבלוק באמת ייתפס. הדוגמה הקלאסית היא קוד שנשלח להרצה ב Thread נפרד, וזה נראה ככה:

class Array
  def pmap(&block)
    each do |i|
      Thread.new { block.call(i) }
    end
    self
  end
end

begin
  [1, 2, 3].pmap do |i|
    raise 'Stop' if i.even?
  end
rescue => e
  puts "Error: #{e.message}"
end

פונקציית pmap שהגדרתי על Array שולחת את הבלוק לרוץ ב thread נפרד ולכן ה Exception שהבלוק זורק לא נתפס ב Thread הראשי. דרך אחת לטפל בקוד כזה היא להקפיד להעביר את ה Exception ל Thread הראשי מתוך pmap, כלומר:

class Array
  def pmap(&block)
    threads = each.map do |i|
      Thread.new do
        block.call(i)
      end
    end

    threads.each(&:join)
    threads.each(&:value)
  end
end

והפעם הפעלה תדפיס את השגיאה:

#<Thread:0x000000012233cbd8 a.rb:4 run> terminated with exception (report_on_exception is true):
a.rb:15:in `block in <main>': Stop (RuntimeError)
        from a.rb:5:in `block (2 levels) in pmap'
Error: Stop