English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

الاستثناءات لـ Ruby

تكون الأعطال مرتبطة دائمًا بالتنفيذ. إذا فتحت ملفًا غير موجود ولم تتعامل مع هذا الحالة بشكل صحيح، فإن برنامجك يعتبر من البرامج منخفضة الجودة.

إذا حدث خطأ، يتوقف البرنامج. تستخدم الأخطاء لمعالجة أنواع مختلفة من الأخطاء، التي قد تحدث أثناء تنفيذ البرنامج، لذا يجب اتخاذ إجراءات مناسبة، حتى لا يتوقف البرنامج بشكل كامل.

يقدم لـ Ruby آلية ممتازة للتعامل مع الأخطاء. يمكننا begin/end أضف إلى الكود المحتمل أن يرفع خطأ في البloc، باستخدام rescue الفقرة تعطي لـ Ruby معرفة أنواع الأخطاء التي يجب التعامل معها بشكل ممتاز.

اللغة

begin # بداية
 
 raise.. # قم برفع الخطأ
 
rescue [ExceptionType = StandardException] # قم بقبض على نوع معين من الأخطاء، القيمة الافتراضية هي StandardException
 $! # يعبر عن معلومات الخطأ
 $@ # يعبر عن موقع ظهور الخطأ
else # الحالات الأخرى من الأخطاء
 ..
تأكد # مهما كان هناك خطأ أو لا، تدخل إلى هذا الكود
 
end # تنتهي

إلى begin يتم حمايته. rescue كل شيء في rescue و end إلى

من begin كل rescue بعد ذلك، يقوم Ruby بتقارن الاستثناء الذي تم إلقاؤه مع كل من المعامل. إذا كان الاستثناء المسمى في جملة rescue مطابقاً لنوع الاستثناء الحالي أو كان هو فئة استثناء له، فإن التطابق ينجح.

إذا لم يكن الاستثناء مطابقاً لجميع أنواع الأخطاء المحددة، يمكننا في جميع rescue بعد الجملة. else بعد الجملة.

مثال على الإنترنت

#!/usr/bin/ruby
 
begin
   file = open("/unexistant_file")
   if file
      puts "File opened successfully"
   end
rescue
      file = STDIN
end
print file, "==", STDIN, "\n"

نتائج الإنتاج في هذا المثال أعلاه. يمكنك رؤية،STDIN تم استبداله file ، لأنفتحفشل.

#<IO:0xb7d16f84>==#<IO:0xb7d16f84>

استخدام retry الجملة

يمكنك استخدام rescue قالب التقاطع يلتقط الاستثناء، ثم يستخدم retry جملة تبدأ من البداية. begin قالب.

اللغة

begin
    # الاستثناء الذي يلقاه هذا الكود سيتم التقاطعه من قبل جملة rescue أدناه
rescue
    # هذا القالب سيقوم بالتقاطع مع جميع أنواع الاستثناءات
    retry # سيقوم هذا بتحويل التحكم إلى بداية begin
end

مثال على الإنترنت

#!/usr/bin/ruby
 
begin
   file = open("/unexistant_file")
   if file
      puts "File opened successfully"
   end
rescue
   fname = "existant_file"
   retry
end

هنا هو مسار المعالجة:

  • حدث استثناء أثناء الفتح.

  • الانتقال إلى rescue. يتم تعديلfname.

  • الانتقال إلى بداية begin من خلال retry.

  • تم فتح الملف بنجاح هذه المرة.

  • استمر في العملية الأساسية.

ملاحظة:إذا لم يكن الملف المعدل موجودًا، فإن كود هذا المثال سيحاول بشكل لا نهائي. لذا، يجب أن تكون حذرًا عند استخدام معالجة الاستثناءات. retry.

استخدام raise الجملة

يمكنك استخدام raise جملة القاء استثناء. يتم القاء هذا الاستثناء من قبل الطريقة في وقت الطلب. سيتم إصدار الرسالة الثانية كجزء من ذلك.

اللغة

raise 
 
أو
 
raise "Error Message" 
 
أو
 
raise ExceptionType, "Error Message"
 
أو
 
raise ExceptionType, "Error Message" condition

الشكل الأول ببساطة يعيد القاء الاستثناء الحالي (إذا لم يكن هناك استثناء حالي فيمكنه القاء RuntimeError). يتم استخدام هذا في برنامج معالجة الاستثناءات قبل إدخال الاستثناء.

الشكل الثاني ينشئ استثناءً جديداً RuntimeError استثناء، يضبط رسالته بالشكل المحدد. ثم يُقذف الاستثناء بعد ذلك إلى قائمة التتابع الطلبية.

الشكل الثالث يستخدم المعامل الأول لإنشاء استثناء، ثم يضبط الرسالة المتعلقة بالمعامل الثاني.

النوع الرابع يشبه النوع الثالث، يمكنك إضافة أي جملة شرطية إضافية (مثل}} unless)لتحفيز الاستثناء.

مثال على الإنترنت

#!/usr/bin/ruby
 
begin  
    puts 'أنا قبل raise.'  
    raise 'An error has occurred.'  
    puts 'أنا بعد raise.'  
rescue  
    puts 'أنا تم إنجاز الإنجاز.'  
end  
puts 'أنا بعد كتلة begin.'

نتائج الإخراج للعينة أعلاه هي:

أنا قبل raise.  
أنا تم إنجاز الإنجاز.  
أنا بعد كتلة begin.

عرض آخر raise مثال على الاستخدام:

مثال على الإنترنت

#!/usr/bin/ruby
 
begin  
  raise 'A test exception.'  
rescue Exception => e  
  puts e.message  
  puts e.backtrace.inspect  
end

نتائج الإخراج للعينة أعلاه هي:

A test exception.
["main.rb:4"]

استخدام ensure الجملة

في بعض الأحيان، قد تحتاج إلى تأكد من أن بعض العمليات يتم تنفيذها عند انتهاء كتلة الكود. على سبيل المثال، قد تكون قد فتحت ملفًا عند الدخول إلى الكتلة، وعندما تخرج من الكتلة، تحتاج إلى التأكد من إغلاق الملف.

ensure ما تقوم به الجملة هو هذا. يتم وضع ensure بعد آخر rescue ويتضمن كتلة من الأوامر التي يتم تنفيذها دائمًا عند انتهاء الكتلة، بغض النظر عما إذا كانت الكتلة غادرت بشكل طبيعي، أو تم طرد استثناء مع معالجته، أو انتهت بسبب استثناء لم يتم القبض عليه،ensure الكتل دائمًا ما تنفذ.

اللغة

begin 
   #.. عملية
   #.. تحفيز استثناء
rescue 
   #.. معالجة الأخطاء 
ensure 
   #.. تأكد من التنفيذ في النهاية
   #.. هذا سيتم دائمًا تنفيذه
end

مثال على الإنترنت

begin
  raise 'A test exception.'
rescue Exception => e
  puts e.message
  puts e.backtrace.inspect
ensure
  puts "تأكد من التنفيذ"
end

نتائج الإخراج للعينة أعلاه هي:

A test exception.
["main.rb:4"]
تأكد من التنفيذ

استخدام else الجملة

إذا تم تقديم else جملة، عادة ما يتم وضعها في rescue بعد الجملة، أي ensure من قبل.

else يتم تنفيذ جسم الجملة فقط إذا لم يكن هناك استثناء يُطرح في الجسم الكامل للكود.

اللغة

begin 
   #.. عملية 
   #.. تحفيز استثناء
rescue 
   #.. معالجة الأخطاء
else
   #.. إذا لم يكن هناك استثناء يتم تنفيذ
ensure 
   #.. تأكد من التنفيذ في النهاية
   #.. هذا سيتم دائمًا تنفيذه
end

مثال على الإنترنت

begin
 # قم بتحفيز 'A test exception.'
 puts "أنا لا أرفع استثناء"
rescue Exception => e
  puts e.message
  puts e.backtrace.inspect
else
   puts "تهاني-- لا توجد أخطاء!"
ensure
  puts "تأكد من التنفيذ"
end

نتائج الإخراج للعينة أعلاه هي:

أنا لا أرفع استثناء
تهاني-- لا توجد أخطاء!
تأكد من التنفيذ

يمكن استخدام متغير $! لالتقاط رسائل الأخطاء المطلقة.

Catch و Throw

يستطيع نظام raise و rescue التخلي عن التنفيذ عند حدوث خطأ، أحيانًا تحتاج إلى الابتعاد عن بنيات تنسيق عميقة عند معالجة الحالات الطبيعية. في هذه الحالة، يأتي دور catch و throw.

catch تم تعريف قالب يستخدم الاسم المحدد (يمكن أن يكون Symbol أو String) كعلامة. سيعمل القالب بشكل طبيعي حتى يواجه throw.

اللغة

throw :lablename
#.. لن يتم تنفيذ هذا
catch :lablename do
#.. سيتم مطابقة التنفيذ بعد throw
end
 
أو
 
throw :lablename condition
#.. لن يتم تنفيذ هذا
catch :lablename do
#.. سيتم مطابقة التنفيذ بعد throw
end

مثال على الإنترنت

في المثال التالي، إذا أدخل المستخدم '!' كرد فعل على أي إشارة، يستخدم throw للإنهاء التفاعل مع المستخدم.

مثال على الإنترنت

def promptAndGet(prompt)
   print prompt
   res = readline.chomp
   throw :quitRequested if res == "!"
   return res
end
 
catch :quitRequested do
   name = promptAndGet("Name: ")
   age = promptAndGet("Age: ")
   sex = promptAndGet("Sex: ")
   # ..
   # معالجة المعلومات
end
promptAndGet("Name:")

يحتاج البرنامج المذكور أعلاه إلى تفاعل بشري، يمكنك تجربته على جهازك. نتائج التنفيذ في هذا المثال هي:

الاسم: Ruby on Rails
العمر: 3
الجنس:!
الاسم:Just Ruby

Class Exception

تقوم الفئات والمجموعات القياسية لـ Ruby بطرح استثنائات. تتكون جميع فئات الاستثناء من سلسلة، بما في ذلك Class Exception في القمة. الطبقة التالية تحتوي على سبعة أنواع مختلفة:

  • Interrupt

  • NoMemoryError

  • SignalException

  • ScriptError

  • StandardError

  • SystemExit

Fatal هو استثناء آخر في هذا الطبقة، ولكن معالج Ruby يستخدمه داخليًا فقط.

ScriptError و StandardError بعض الفروع لها، ولكن لا نحتاج إلى معرفة هذه التفاصيل هنا. الأهم من ذلك هو إنشاء فئات استثنائية الخاصة بنا، يجب أن تكون فروع Class Exception أو فروعها.

دعونا نرى مثالاً:

مثال على الإنترنت

class FileSaveError < StandardError
   attr_reader :reason
   def initialize(reason)
      @reason = reason
   end
end

الآن، لنرى المثال التالي، الذي سيستخدم الاستثناء المذكور أعلاه:

مثال على الإنترنت

File.open(path, "w") do |file|
begin
    # كتابة البيانات...
rescue
    # خطأ يحدث
    raise FileSaveError.new($!)
end
end

في هذا السياق، السطر الأكثر أهمية هو raise FileSaveError.new($!)نحن نستخدم raise لتحديد أن الاستثناء قد حدث، ونقوم بتحويله إلى مثال جديد لـ FileSaveError، بسبب استثناء معين قد يؤدي إلى فشل كتابة البيانات.