2010-09-27 18 views
28

Ứng dụng của tôi (Ruby 1.9.2) có thể tăng các ngoại lệ khác nhau, bao gồm cả ngắt kết nối mạng. Tôi rescue Exception => e, sau đó thực hiện case/when để xử lý chúng theo các cách thức kém hiệu quả, nhưng một số lỗi đi qua các trường hợp của tôi thẳng đến else.Làm thế nào để bắt Errno :: ECONNRESET lớp trong "trường hợp khi"?

rescue Exception => e 
    p e.class 
    case e.class 
     when Errno::ECONNRESET 
      p 1 
     when Errno::ECONNRESET,Errno::ECONNABORTED,Errno::ETIMEDOUT 
      p 2 
     else 
      p 3 
    end 
end 

Prints:

Errno::ECONNRESET 
3 
+1

Giải cứu các lớp lỗi của bạn trong một khối đa nhiệm và sau đó bạn có thể tránh hoàn toàn câu lệnh. –

Trả lời

49

này là do cách điều hành === hoạt động trên lớp Class

Các case tuyên bố internally calls các === phương pháp trên đối tượng bạn đang đánh giá lại. Nếu bạn muốn thử nghiệm cho lớp học e, bạn chỉ cần thử nghiệm với e, không phải e.class. Đó là vì e.class sẽ rơi vào trường hợp when Class, bởi vì, vâng, e.class là một Lớp.

rescue Exception => e 
    case e 
     when Errno::ECONNRESET 
      p 1 
     when Errno::ECONNRESET,Errno::ECONNABORTED,Errno::ETIMEDOUT 
      p 2 
     else 
      p 3 
    end 
end 

Vâng, Ruby có thể có ngữ nghĩa lạ đôi khi

+4

Vâng, kỳ lạ. 1 === 1 => đúng. Mảng === Mảng => sai. – Nakilon

+0

Uh. Tôi cá rằng 'Mảng === Lớp' sẽ thành hiện thực, nhưng bây giờ tôi đang bối rối. Nhờ bình luận của bạn bây giờ tôi không thể ngủ:/ – Chubas

+4

Tất nhiên, bây giờ nó có ý nghĩa. '===' được gọi trên phần tử mà bạn so sánh. Vì vậy, 'Class === Array',' String === "foobar" 'và'/foo/=== "foobar" 'tất cả trở về true. – Chubas

1

Vâng nó phụ thuộc vào việc bạn tham khảo các lớp học hoặc hằng số. Tôi có ví dụ đã phải sử dụng câu lệnh trường hợp sau đây để có được một loại nhất định của phát hiện làm việc

def fail(exception_error) 
exception = exception_error 
case exception.class 
    when /HTTPClient::ConnectTimeoutError.new/ 
    status = 'CONNECTION TIMEOUT' 
    connection_status = 'DOWN' 
    else 
    status = 'UNKNOWN FAILURE' 
    connection_status = 'DOWN' 
end 

Nhưng đó là bởi vì tôi đang làm việc với các ngoại lệ Lớp thực tế không phải là không đổi. HttpClient được nâng cao một đối tượng lớp học thực tế:

class TimeoutError < RuntimeError 
end 
class ConnectTimeoutError < TimeoutError 
end 

Dưới đây là một thực tế khó hiểu:

error = HTTPClient::ConnectTimeoutError.new 
HTTPClient::ConnectTimeoutError === error 
#=> true 
error === HTTPClient::ConnectTimeoutError 
#=> false 

Không chắc chắn những gì để làm điều đó.

+0

phiên bản ruby ​​nào là 'sự thật khó hiểu' chạy trong? –

Các vấn đề liên quan