Với những gì tài liệu lõi ruby của Exception
, từ đó tất cả các lỗi khác kế thừa, nói về #message
Trả về kết quả của cách gọi exception.to_s. Thông thường, điều này trả lại thông báo hoặc tên của ngoại lệ. Bằng cách cung cấp phương thức to_str, ngoại lệ đồng ý được sử dụng trong đó các chuỗi được mong đợi.
http://ruby-doc.org/core-1.9.3/Exception.html#method-i-message
tôi sẽ lựa chọn xác định lại to_s
/to_str
hoặc initializer. Đây là một ví dụ mà chúng ta muốn biết, theo một cách có thể đọc được chủ yếu là con người, khi một dịch vụ bên ngoài không làm được điều gì đó.
LƯU Ý: Chiến lược thứ hai bên dưới sử dụng các phương pháp chuỗi khá đẹp, chẳng hạn như demodualize
, có thể hơi phức tạp và do đó có khả năng không thực hiện trong một ngoại lệ. Bạn cũng có thể thêm nhiều đối số vào chữ ký phương thức, nếu bạn cần.
Overriding #to_s Chiến lượckhông #to_str, nó hoạt động khác nhau
module ExternalService
class FailedCRUDError < ::StandardError
def to_s
'failed to crud with external service'
end
end
class FailedToCreateError < FailedCRUDError; end
class FailedToReadError < FailedCRUDError; end
class FailedToUpdateError < FailedCRUDError; end
class FailedToDeleteError < FailedCRUDError; end
end
điều khiển Output
begin; raise ExternalService::FailedToCreateError; rescue => e; e.message; end
# => "failed to crud with external service"
begin; raise ExternalService::FailedToCreateError, 'custom message'; rescue => e; e.message; end
# => "failed to crud with external service"
begin; raise ExternalService::FailedToCreateError.new('custom message'); rescue => e; e.message; end
# => "failed to crud with external service"
raise ExternalService::FailedToCreateError
# ExternalService::FailedToCreateError: failed to crud with external service
Overriding #initialize Chiến lược
Đây là chiến lược gần với triển khai nhất mà tôi đã sử dụng trong đường ray. Như đã nói ở trên, nó sử dụng các phương pháp demodualize
, underscore
và humanize
ActiveSupport
. Nhưng điều này có thể dễ dàng loại bỏ, như trong chiến lược trước.
module ExternalService
class FailedCRUDError < ::StandardError
def initialize(service_model=nil)
super("#{self.class.name.demodulize.underscore.humanize} using #{service_model.class}")
end
end
class FailedToCreateError < FailedCRUDError; end
class FailedToReadError < FailedCRUDError; end
class FailedToUpdateError < FailedCRUDError; end
class FailedToDeleteError < FailedCRUDError; end
end
điều khiển Output
begin; raise ExternalService::FailedToCreateError; rescue => e; e.message; end
# => "Failed to create error using NilClass"
begin; raise ExternalService::FailedToCreateError, Object.new; rescue => e; e.message; end
# => "Failed to create error using Object"
begin; raise ExternalService::FailedToCreateError.new(Object.new); rescue => e; e.message; end
# => "Failed to create error using Object"
raise ExternalService::FailedCRUDError
# ExternalService::FailedCRUDError: Failed crud error using NilClass
raise ExternalService::FailedCRUDError.new(Object.new)
# RuntimeError: ExternalService::FailedCRUDError using Object
Demo Tool
Đây là một bản demo để hiển thị cứu và nhắn tin tình hình thực hiện ở trên. Lớp nâng cao các ngoại lệ là một API giả để Cloudinary. Chỉ cần đổ một trong các chiến lược trên vào bảng điều khiển đường ray của bạn, tiếp theo là điều này.
require 'rails' # only needed for second strategy
module ExternalService
class FailedCRUDError < ::StandardError
def initialize(service_model=nil)
@service_model = service_model
super("#{self.class.name.demodulize.underscore.humanize} using #{@service_model.class}")
end
end
class FailedToCreateError < FailedCRUDError; end
class FailedToReadError < FailedCRUDError; end
class FailedToUpdateError < FailedCRUDError; end
class FailedToDeleteError < FailedCRUDError; end
end
# Stub service representing 3rd party cloud storage
class Cloudinary
def initialize(*error_args)
@error_args = error_args.flatten
end
def create_read_update_or_delete
begin
try_and_fail
rescue ExternalService::FailedCRUDError => e
e.message
end
end
private def try_and_fail
raise *@error_args
end
end
errors_map = [
# Without an arg
ExternalService::FailedCRUDError,
ExternalService::FailedToCreateError,
ExternalService::FailedToReadError,
ExternalService::FailedToUpdateError,
ExternalService::FailedToDeleteError,
# Instantiated without an arg
ExternalService::FailedCRUDError.new,
ExternalService::FailedToCreateError.new,
ExternalService::FailedToReadError.new,
ExternalService::FailedToUpdateError.new,
ExternalService::FailedToDeleteError.new,
# With an arg
[ExternalService::FailedCRUDError, Object.new],
[ExternalService::FailedToCreateError, Object.new],
[ExternalService::FailedToReadError, Object.new],
[ExternalService::FailedToUpdateError, Object.new],
[ExternalService::FailedToDeleteError, Object.new],
# Instantiated with an arg
ExternalService::FailedCRUDError.new(Object.new),
ExternalService::FailedToCreateError.new(Object.new),
ExternalService::FailedToReadError.new(Object.new),
ExternalService::FailedToUpdateError.new(Object.new),
ExternalService::FailedToDeleteError.new(Object.new),
].inject({}) do |errors, args|
begin
errors.merge!(args => Cloudinary.new(args).create_read_update_or_delete)
rescue => e
binding.pry
end
end
if defined?(pp) || require('pp')
pp errors_map
else
errors_map.each{ |set| puts set.inspect }
end
Không 'giải cứu Ngoại lệ => e'. Nó rộng hơn so với 'rescue => e' mặc định mở rộng từ' StandardError' và bắt tất cả mọi thứ bao gồm Ctrl + C. Tôi sẽ làm 'giải cứu MyCustomError => e'. –
@RyanTaylor Tôi đã chỉnh sửa câu hỏi của mình để có cách tiếp cận phù hợp hơn. – MarioDS