Mengingat apa yang Exception
dinyatakan oleh dokumentasi inti rubi , yang mewarisi semua kesalahan lainnya, nyatakan#message
Menampilkan hasil pemanggilan exception.to_s. Biasanya ini mengembalikan pesan atau nama pengecualian. Dengan menyediakan metode to_str, pengecualian setuju untuk digunakan di tempat yang diharapkan Strings.
http://ruby-doc.org/core-1.9.3/Exception.html#method-i-message
Saya akan memilih untuk mendefinisikan ulang to_s
/ to_str
atau penginisialisasi. Berikut adalah contoh di mana kami ingin tahu, dengan cara yang sebagian besar dapat dibaca manusia, ketika layanan eksternal gagal melakukan sesuatu.
CATATAN: Strategi kedua di bawah ini menggunakan metode string rails yang cantik, seperti demodualize
, yang mungkin sedikit rumit dan karena itu berpotensi tidak bijaksana untuk dilakukan dalam pengecualian. Anda juga bisa menambahkan lebih banyak argumen ke tanda tangan metode, jika Anda membutuhkannya.
Mengganti Strategi #to_s bukan #to_str, cara kerjanya berbeda
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
Output Konsol
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
Mengganti Strategi #initialize
Ini adalah strategi yang paling dekat dengan implementasi yang saya gunakan di rel. Seperti disebutkan di atas, menggunakan demodualize
, underscore
dan humanize
ActiveSupport
metode. Tapi ini bisa dengan mudah dihilangkan, seperti pada strategi sebelumnya.
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
Output Konsol
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
Alat Demo
Ini adalah demo untuk menunjukkan penyelamatan dan pengiriman pesan dari implementasi di atas. Kelas yang memunculkan pengecualian adalah API palsu ke Cloudinary. Cukup buang salah satu strategi di atas ke konsol rel Anda, diikuti dengan ini.
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
rescue Exception => e
. Ini lebih luas dari defaultrescue => e
yang diturunkan dariStandardError
, dan menangkap semuanya termasuk Ctrl + C. Aku akan melakukannyarescue MyCustomError => e
.