Computer >> Máy Tính >  >> Lập trình >> Ruby

Giải quyết các ngoại lệ trong Ruby

Một ngoại lệ đã nâng có thể được cứu để ngăn ứng dụng của bạn gặp sự cố khi nó lên đến đầu ngăn xếp cuộc gọi. Trong Ruby, chúng tôi sử dụng rescue từ khóa cho điều đó.

Khi giải cứu một ngoại lệ trong Ruby, bạn có thể chỉ định một lớp lỗi cụ thể sẽ được giải cứu khỏi.

begin
  raise 'This exception will be rescued!'
rescue StandardError => e
  puts "Rescued: #{e.inspect}"
end

Lưu ý :Khi sử dụng raise mà không chỉ định một lớp ngoại lệ, Ruby sẽ mặc định là RuntimeError .

Bên cạnh việc chỉ định một lớp ngoại lệ duy nhất để giải cứu, bạn có thể chuyển một mảng các lớp ngoại lệ vào rescue từ khóa. Điều này sẽ cho phép bạn phản hồi nhiều lỗi theo cùng một cách.

begin
  raise 'This exception will be rescued!'
rescue StandardError, AnotherError => e
  puts "Rescued: #{e.inspect}"
end

Nhiều rescue các khối có thể được sử dụng để xử lý các lỗi khác nhau theo những cách khác nhau. Điều này có thể hữu ích khi làm việc với một thư viện tạo ra các ngoại lệ khác nhau cho các tình huống khác nhau.

begin
  raise 'This exception will be rescued!'
rescue StandardError => e
  puts "Rescued: #{e.inspect}"
rescue AnotherError => e
  puts "Rescued, but with a different block: #{e.inspect}"
end

Phân cấp ngoại lệ

Hệ thống phân cấp ngoại lệ của Ruby được sử dụng để phân biệt giữa các loại lỗi khác nhau, đồng thời cung cấp cho bạn khả năng giải cứu khỏi một nhóm lỗi mà không cần chỉ định tất cả chúng.

Mặc dù các thư viện có thể định nghĩa các lớp con ngoại lệ của riêng chúng, nhưng danh sách các lớp con ngoại lệ được tích hợp sẵn trên Ruby 2.5 trông giống như sau:

- NoMemoryError
- ScriptError
    - LoadError
    - NotImplementedError
    - SyntaxError
- SecurityError
- SignalException
    - Interrupt
- StandardError (default for `rescue`)
    - ArgumentError
        - UncaughtThrowError
    - EncodingError
    - FiberError
    - IOError
        - EOFError
    - IndexError
        - KeyError
        - StopIteration
    - LocalJumpError
    - NameError
        - NoMethodError
    - RangeError
        - FloatDomainError
    - RegexpError
    - RuntimeError (default for `raise`)
    - SystemCallError
        - Errno::*
    - ThreadError
    - TypeError
    - ZeroDivisionError
- SystemExit
- SystemStackError
- fatal (impossible to rescue)

Khi bỏ qua lớp ngoại lệ trong rescue khối, StandardError được giả định. Bởi vì ArgumentErrorNoMethodError là các lớp con của StandardError , chúng sẽ được giải cứu khi chúng xuất hiện trong khối.

Một ví dụ điển hình về cách hoạt động của hệ thống phân cấp ngoại lệ là SystemCallError , là một lớp ngoại lệ phụ thuộc vào nền tảng cấp thấp. Nó được nhìn thấy thường xuyên nhất khi đọc hoặc ghi vào tệp.

Ruby’s File.read phương thức sẽ đưa ra một ngoại lệ nếu nó không đọc được tệp. Điều đó có thể xảy ra vì một số lý do, chẳng hạn như tệp không tồn tại hoặc chương trình không có quyền chính xác để đọc nó.

Vì những vấn đề này phụ thuộc vào nền tảng, nên Ruby có thể đưa ra các ngoại lệ khác nhau tùy thuộc vào loại hệ điều hành đang chạy trên máy. Đối với các lỗi cấp thấp như thế này, Ruby triển khai một danh sách khác gồm Errno::* -các ngoại lệ cho mỗi nền tảng.

Tất cả Errno::* này ngoại lệ là các lớp con của SystemCallError . Mặc dù chúng dành riêng cho nền tảng, chúng vẫn có thể được sử dụng trong rescue chặn bằng cách giải cứu khỏi SystemCallError .

begin
  File.read("does/not/exist")
rescue SystemCallError => e
  puts "Rescued: #{e.inspect}"
end

Nuốt ngoại lệ

Thông thường, tốt nhất là càng cụ thể càng tốt khi giải cứu các trường hợp ngoại lệ, để ngăn việc vô tình nuốt các trường hợp ngoại lệ.

Cứu hộ
image = nil
 
begin
  File.read(image.filename)
rescue
  puts "File can't be read!"
end

Trong ví dụ này, image biến là nil , vì vậy nó tạo ra một NoMethodError khi chúng tôi cố gắng gọi #filename trên đó (NoMethodError: undefined method `filename' for nil:NilClass ). Bởi vì mọi StandardError lớp con được giải cứu khỏi (bao gồm NoMethodError ), ngoại lệ bị nuốt và thông báo “Không thể đọc tệp!” - được in. Điều này ẩn một lỗi có thể xảy ra trong mã.

Lưu ý :Mặc dù có thể, nhưng sử dụng Exception lớp cha trong rescue khối rất không được khuyến khích.

Bạn có bất kỳ câu hỏi nào về việc nâng cao hoặc giải cứu các trường hợp ngoại lệ trong Ruby? Vui lòng cho chúng tôi biết tại @AppSignal. Tất nhiên, chúng tôi muốn biết bạn thích bài viết này như thế nào hoặc nếu bạn có chủ đề khác mà bạn muốn biết thêm.