আপনি যখন রুবিতে একটি রেসকিউ ক্লজ ব্যবহার করেন, তখন আপনি কী ধরনের ব্যতিক্রম উদ্ধার করতে চান তা নির্দিষ্ট করতে পারেন। আপনাকে যা করতে হবে তা হল এর মত ব্যতিক্রম ক্লাসের একটি তালিকা প্রদান করুন:
begin
raise RuntimeError
rescue RuntimeError, NoMethodError
puts "rescued!"
end
কিন্তু আপনি যদি কোডটি লেখার সময় ব্যতিক্রম ক্লাসটি কী হবে তা যদি আপনি না জানেন? সবচেয়ে সুস্পষ্ট উত্তর হল সমস্ত ব্যতিক্রম উদ্ধার করা, কিছু ধরণের পরীক্ষা করা এবং তারপরে পাস না হওয়া ব্যতিক্রমগুলিকে পুনরায় উত্থাপন করা। এরকম কিছু:
begin
raise "FUBAR! The ship's going down!"
rescue => e
raise unless e.message =~ /^FUBAR/
... do something ...
end
কিন্তু যে এত বিরক্তিকর! এছাড়াও, এটি একটি খুব শুষ্ক পদ্ধতির নয়। এটা অনেক বেশি আকর্ষণীয় হবে যদি আমরা কোনোভাবে রেসকিউ ক্লজটিকে আমাদের শর্তের সাথে মেলে শুধুমাত্র রেসকিউ ব্যতিক্রম বলতে পারি। এবং যেহেতু এটি রুবি, আমরা এটি করতে পারি!
কিভাবে রেসকিউ ব্যতিক্রমের সাথে মেলে
রেসকিউ ব্লকের ভিতরে একটি ব্যতিক্রম ঘটলে, রুবি ইন্টারপ্রেটার আপনার দেওয়া ব্যতিক্রম ক্লাসের তালিকার বিপরীতে ব্যতিক্রমের ক্লাস পরীক্ষা করে। যদি একটি মিল থাকে, তবে ব্যতিক্রমটি উদ্ধার করা হয়।
মিলটি এইরকম কিছু দেখায়:
exception_classes_to_rescue.any? do |c|
c === raised_exception.class
end
রুবিতে অন্য অপারেটরের মতো, ===
সহজভাবে একটি পদ্ধতি। এই ক্ষেত্রে এটি c
এর একটি পদ্ধতি . তাহলে আমরা কি করতে পারি যদি আমরা আমাদের নিজস্ব ===
সংজ্ঞায়িত করি পদ্ধতি?
নীচের উদাহরণে আমি Anything
নামে একটি ক্লাস তৈরি করছি যেখানে Anything === x
x এর যেকোনো মানের জন্য সত্য ফেরত দেয়। যদি আমি এই শ্রেণীটিকে উদ্ধারের যুক্তি হিসাবে দিই, তবে এটি সমস্ত ব্যতিক্রমগুলিকে উদ্ধার করে।
class Anything
def self.===(exception)
true
end
end
begin
raise EOFError
rescue Anything
puts "It rescues ANYTHING!"
end
যদিও সমস্ত ব্যতিক্রমগুলি উদ্ধার করার আরও ভাল উপায় রয়েছে, এই কোডটি আকর্ষণীয় কারণ এটি আমাদের দুটি জিনিস দেখায়:
-
আপনি রেসকিউ ক্লজ ক্লাস দিতে পারেন যেগুলি
Exception
থেকে উত্তরাধিকারসূত্রে পাওয়া যায় না , যতক্ষণ না তারা===
প্রয়োগ করে -
আপনি যদি
===
নিয়ন্ত্রণ করেন , আপনি কোন ব্যতিক্রমগুলি উদ্ধার করা হবে তা নিয়ন্ত্রণ করতে পারেন৷
বার্তার উপর ভিত্তি করে ব্যতিক্রমগুলি উদ্ধার করা
আমরা এখন যা জানি তা জেনে, কোড লেখা সহজ যা শুধুমাত্র ব্যতিক্রমগুলিকে উদ্ধার করে যদি ব্যতিক্রমের বার্তাটি একটি প্যাটার্নের সাথে মিলে যায়৷
class AllFoobarErrors
def self.===(exception)
# rescue all exceptions with messages starting with FOOBAR
exception.message =~ /^FOOBAR/
end
end
begin
raise EOFError, "FOOBAR: there was an eof!"
rescue AllFoobarErrors
puts "rescued!"
end
কাস্টম বৈশিষ্ট্যের উপর ভিত্তি করে ব্যতিক্রমগুলি উদ্ধার করা
যেহেতু আপনার কাছে ব্যতিক্রম বস্তুর অ্যাক্সেস আছে, আপনার ম্যাচার সেই বস্তুর ভিতরে থাকা যেকোনো ডেটা ব্যবহার করতে পারে।
এক মুহুর্তের জন্য কল্পনা করুন যে আপনার কাছে একটি ব্যতিক্রম আছে যার একটি কাস্টম বৈশিষ্ট্য রয়েছে যার নাম "তীব্রতা"। আপনি ব্যতিক্রমের সমস্ত "নিম্ন তীব্রতা" ঘটনাগুলিকে গ্রাস করতে চান, তবে যেকোনো "উচ্চ তীব্রতা" ঘটনাগুলিকে পাস করতে দিন৷ আপনি এটিকে এভাবে বাস্তবায়ন করতে পারেন:
class Infraction < StandardError
attr_reader :severity
def initialize(severity)
@severity = severity
end
end
class LowSeverityInfractions
def self.===(exception)
exception.is_a?(Infraction) && exception.severity == :low
end
end
begin
raise Infraction.new(:low)
rescue LowSeverityInfractions
puts "rescued!"
end
এটিকে গতিশীল করা
এই সবই বেশ চমৎকার, কিন্তু এতে প্রচুর বয়লারপ্লেট কোড জড়িত। প্রতিটি ম্যাচারের জন্য ম্যানুয়ালি আলাদা ক্লাস সংজ্ঞায়িত করা অত্যধিক বলে মনে হচ্ছে। সৌভাগ্যবশত আমরা একটু মেটাপ্রোগ্রামিং ব্যবহার করে এটিকে কিছুটা শুকিয়ে নিতে পারি।
নীচের উদাহরণে, আমরা একটি পদ্ধতি সংজ্ঞায়িত করছি যা আমাদের জন্য ম্যাচার ক্লাস তৈরি করে। আপনি একটি ব্লকের মাধ্যমে ম্যাচিং লজিক প্রদান করেন এবং ম্যাচিং জেনারেটর একটি নতুন ক্লাস তৈরি করে যা তার ===
এর ভিতরে ব্লক ব্যবহার করে পদ্ধতি।
def exceptions_matching(&block)
Class.new do
def self.===(other)
@block.call(other)
end
end.tap do |c|
c.instance_variable_set(:@block, block)
end
end
begin
raise "FOOBAR: We're all doomed!"
rescue exceptions_matching { |e| e.message =~ /^FOOBAR/ }
puts "rescued!"
end
লবণের একটি দানা
রুবির অনেক দুর্দান্ত কৌশলের মতো, আমি ঠিক করতে পারি না যে এই সবগুলি পাগলামি নাকি একটি দুর্দান্ত ধারণা। হয়তো এটা উভয়ের সামান্য. যদিও আমি স্পষ্টভাবে সুপারিশ করব না যে আপনি প্রথম পছন্দ হিসাবে এই কৌশলটির জন্য পৌঁছান, আমি দেখতে পাচ্ছি যে এটি উপরেরটির মতো পরিস্থিতিতে কীভাবে কার্যকর হবে যেখানে আপনি তীব্রতার উপর ভিত্তি করে ব্যতিক্রমগুলি উদ্ধার করতে চান। যাই হোক না কেন, এটি আপনার টুলবেল্টের আরেকটি টুল!