มักจะเป็นประโยชน์ที่จะได้รับข้อยกเว้นล่าสุด แม้ว่าโค้ดของคุณจะไม่ได้ควบคุมวงจรชีวิตของข้อยกเว้นนั้นก็ตาม ลองนึกภาพว่าคุณต้องการเพิ่มการตรวจจับข้อขัดข้องพื้นฐานให้กับแอปพลิเคชันของคุณ คุณต้องการบันทึกข้อมูลเพิ่มเติมเกี่ยวกับข้อขัดข้องที่เกิดขึ้นอันเป็นผลมาจากข้อยกเว้นที่ตรวจไม่พบ
ขั้นตอนแรกคือการเพิ่มตัวจัดการที่ทำงานทุกครั้งที่แอปพลิเคชันของคุณออก ทำได้ง่ายมากโดยใช้วิธี at_exit ของเคอร์เนล Ruby
at_exit
puts "the app exited"
end
แต่เราจะรู้ได้อย่างไรว่าการโทรกลับทางออกถูกเรียกใช้อันเป็นผลมาจากข้อยกเว้นหรือไม่ Ruby ให้ชื่อ $!
. ที่เข้ารหัสลับ ตัวแปรระดับโลก มันมีข้อยกเว้นที่เพิ่งยกขึ้นล่าสุดที่เกิดขึ้นที่ใดที่หนึ่งในสแต็กการโทรปัจจุบัน
การใช้ $!
. เป็นเรื่องเล็กน้อย เพื่อตรวจสอบว่าโปรแกรมกำลังออกจากโปรแกรมเนื่องจากข้อยกเว้น หน้าตาประมาณนี้:
at_exit do
save_error_to_log($!) if $!
end
ข้อจำกัดของ $!
ขออภัย $!
เมธอดจะใช้ได้ก็ต่อเมื่อข้อยกเว้นเกิดขึ้นที่ใดที่หนึ่งในสแต็กการโทรปัจจุบัน หากคุณกู้คืนข้อยกเว้น ให้ลองเข้าถึง $!
นอกเงื่อนไขการช่วยเหลือ คุณจะได้ศูนย์
begin
raise "x"
rescue
puts $! # => RuntimeError
end
puts $! # => nil
นี่หมายความว่า $!
ค่อนข้างไร้ประโยชน์ภายในเปลือกเช่น IRB บ่อยครั้งใน IRB ฉันจะเรียกใช้เมธอดและรับข้อยกเว้น บางครั้งฉันต้องการที่จะได้รับข้อยกเว้นของวัตถุนั้น แต่ $!
ใช้ไม่ได้กับสิ่งนี้
irb(main):001:0> 1/0
ZeroDivisionError: divided by 0
from (irb):1:in `/'
irb(main):002:0> $!
=> nil
กำลังดำเนินการ $! กับ PRY
PRY หลีกเลี่ยงข้อจำกัดของ $!
โดยการเพิ่มตัวแปรท้องถิ่น _ex_
. ตัวแปรนี้มีข้อยกเว้นที่ยังไม่ได้ตรวจจับล่าสุด
[1] pry(main)> raise "hi"
RuntimeError: hi
from (pry):1:in `__pry__'
[2] pry(main)> _ex_
=> #<RuntimeError: hi>
เหตุผลที่ PRY ทำได้ก็เพราะไม่มีข้อยกเว้นใดๆ ที่ยังไม่ได้ตรวจพบใน PRY หรือ IRB เชลล์จับข้อยกเว้นและแสดงเป็นข้อความแสดงข้อผิดพลาดที่มีรูปแบบสวยงาม
ฉันได้คัดลอกบิตที่เกี่ยวข้องของแหล่ง PRY ด้านล่างแล้ว คุณจะเห็นว่าโค้ดที่ประเมินคำสั่งของคุณอยู่ในบล็อกเริ่มต้น/กู้ภัย/สิ้นสุด เมื่อเกิดข้อยกเว้นที่ช่วยชีวิตได้ PRY จะบันทึกข้อยกเว้นไว้ที่ self.last_exception และต่อมาจะได้รับมอบหมายให้ _ex_
.
# Excerpted from the PRY source at https://github.com/pry/pry/blob/623306966bfa86890ac182bc8375ec9699abe90d/lib/pry/pry_instance.rb#L273
begin
if !process_command_safely(line)
@eval_string << "#{line.chomp}\n" if !line.empty? || !@eval_string.empty?
end
rescue RescuableException => e
self.last_exception = e
result = e
Pry.critical_section do
show_result(result)
end
return
end
ต้องใช้ภาษาอังกฤษ
บางทีคุณอาจพบชื่อตัวแปรเช่น $!
ตาแข็งเล็กน้อย? โชคดีที่ Ruby มีโมดูลที่เรียกว่า "English" ซึ่งให้ตัวแปรทั่วโลกในเวอร์ชันภาษาอังกฤษ ซึ่งดูเหมือนหุ่นยนต์ cusswords
คำพ้องความหมายสำหรับ $!
คือ $ERROR_INFO
. คุณสามารถใช้ได้ทุกที่โดยปกติ $!
.
require "English"
begin
raise "x"
rescue
puts $ERROR_INFO # => RuntimeError
end
และแม้ว่าคำภาษาอังกฤษอื่นๆ ที่เทียบเท่ากันส่วนใหญ่จะไม่เกี่ยวข้องกับหัวข้อของโพสต์ในบล็อกนี้ แต่ฉันก็รวมไว้เพื่อความบันเทิง ตัวแปรภาษาอังกฤษอยู่ทางด้านซ้าย ต้นฉบับอยู่ด้านขวา
$ERROR_INFO | $! |
$ERROR_POSITION | $@ |
$FS | $; |
$FIELD_SEPARATOR | $; |
$OFS | $, |
$OUTPUT_FIELD_SEPARATOR | $, |
$RS | $/ |
$INPUT_RECORD_SEPARATOR | $/ |
$ORS | $\ |
$OUTPUT_RECORD_SEPARATOR | $\ |
$INPUT_LINE_NUMBER | $. |
$NR | $. |
$LAST_READ_LINE | $_ |
$DEFAULT_OUTPUT | $> |
$DEFAULT_INPUT | $< |
$PID | $$ |
$PROCESS_ID | $$ |
$CHILD_STATUS | $? |
$LAST_MATCH_INFO | $~ |
$ละเว้น | $= |
$ARGV | $* |
$MATCH | $& |
$PREMATCH | $` |
$POSTMATCH | $‘ |
$LAST_PAREN_MATCH | $+ |