Exception & StandardError trong Ruby
Bài đăng này đã không được cập nhật trong 8 năm
Trong công việc, đôi khi bạn phải bắt những lỗi như Exception & StandardError
, hiểu rõ hơn về chúng sẽ giúp bạn quản lý công việc tốt hơn.
Bình thường ta hay viết
def some_method
##some code ...
rescue Exception => e
e.message
end
Exception
đơn giản là 1 class
(http://ruby-doc.org/core-2.2.0/Exception.html) dùng để bắt những lỗi được raise
hoặc fail
trong 1 block begin end
, Exception
có những loại 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
Như trong list trên StandardError
cũng chỉ là một dạng Exception
.
Exception
bao gồm cả những lỗi như thiếu bộ nhớ (NoMemoryError
), break khi đang thực hiện thao tác (SignalException::Interrupt
), ví dụ ta dùng tổ hợp phím CTRL_C ...
StandardError
bao gồm những lỗi phổ biến như chia cho 0 (ZeroDivisionError
), không có hoặc gọi tên hàm sai (NameError::NoMethodError
)...
Muốn raise 1 Exception
với 1 message
theo ý mình ta chỉ việc dùng (ví dụ với ZeroDivisionError
):
raise ZeroDivisionError, "some error ..."
Muốn định nghĩa 1 dạng Error
, ta chỉ việc thêm 1 class kế thừa (có thể là StandardError
), sau đó raise
như bình thường :
class SomeError < StandardError
end
def test_error agr
raise SomeError, "some error ..." if agr.nil?
end
def test_another_error agr
agr / 0
rescue ZeroDivisionError
raise SomeError, "some error ..."
end
Muốn xem full backtrace
gọi method e.backtrace
, hàm trả về dạng mảng các dòng báo lỗi.
Muốn thay đổi backtrace
của error
ta dùng method set_backtrace
:
e.set_backtrace(["Hello", "World"])
e.backtrace
Hello
World
Method e.inspect
để xem error
đầy đủ.
Khi viết API, ta thường hay phải raise
các error
khi gặp các trường hợp đặc biệt và đưa ra endpoint
những error_code
dựa trên những dạng error
mà chúng taraise
ra.
Grape
là 1 trong những gem giúp ta làm API
khá, phổ biến.
Khi dùng Grape
làm API
ta thường raise
những class
lỗi tự định nghĩa bằng cách kế thừa class
Grape::Exceptions::ValidationErrors
rồi dùng rescue_from
để catch
lại.
Đối với những lỗi phát sinh trong quá trình sử lý ta cũng có thể dùng rescue_from
để catch
lại, đơn giản nhất là rescue_from :all do |e|
, tuy nhiên chỉ có tác dụng đối với StandardError
và không đối với Exception
.
Grape::Exceptions::ValidationErrors
có base là StandardError
do vậy rescue_from
sẽ bắt được hết error
tự định nghĩa do kế thừa nó.
Trong Grape::Exceptions::ValidationErrors
ta có message
, headers
hoạt động như các attributes
để ta có thể gán thông tin tiện cho việc xử lý lúc catch
lại.
def validate_param! attr_name, params
raise Grape::Exceptions::Validation,
params: [@scope.full_name(attr_name)],
headers: Settings.api_validation.bad_digit_params unless params[attr_name].try(:length).try :<=, @option
end
...
rescue_from Grape::Exceptions::ValidationErrors do |e|
missing_params = bad_format_params = bad_digit_params = []
e.each do |_param, errors|
if errors[:headers] == Settings.api_validation.bad_digit_params
bad_digit_params += errors[:params]
end
end
end
Cảm ơn và hi vọng bài viết giúp ích trong công việc của bạn.
All rights reserved