আপনি যে ধরনের ত্রুটি উত্থাপন করতে চান তা নির্দিষ্ট করার জন্য রুবির রাইজ সিনট্যাক্স আপনাকে কয়েকটি বিকল্প দেয়। নিচের কোডে, আমি রানটাইম এরর বাড়ানোর তিনটি উপায় দেখিয়েছি।
raise "hello"
raise RuntimeError, "hello"
raise RuntimeError.new("hello")
# ...all of the above result in "RuntimeError: hello"
এটা চমৎকার, কিন্তু কি হবে যখন আমি একটি ব্যতিক্রম ছাড়া অন্য কিছু বাড়াতে চাই? যদি আমি একটি সংখ্যা বাড়াতে চাই? আচ্ছা, রুবি আমাকে অনুমতি দেবে না। আমি এই মত একটি ত্রুটি বার্তা পেতে হবে:
raise 1
# TypeError: exception class/object expected
এখন এই বার্তাটি আপনাকে বিশ্বাস করতে পারে যে raise একটি ব্যতিক্রম ক্লাস/অবজেক্ট একটি প্যারামিটার হিসাবে আশা করে। কিন্তু এটা ভুল!
প্রবর্তন করা হচ্ছে exception
পদ্ধতি
আপনি যদি raise foo
করেন raise পদ্ধতিটি আশা করে না যে foo একটি ব্যতিক্রম বস্তু হবে। এটি আশা করে যে যখনই এটি foo.exception
কল করবে তখন এটি একটি ব্যতিক্রম বস্তু পাবে .
মনে রাখার বিষয় হল যে আপনি বাড়াতে যেকোন কিছু পাস করতে পারেন, যতক্ষণ না এটিতে ব্যতিক্রম নামক একটি পদ্ধতি থাকে যা একটি ব্যতিক্রম প্রদান করে।
সুতরাং, আপনি যদি চান, আপনি একটি সংখ্যা বাড়াতে অনুমতি দেওয়ার জন্য রুবির নম্বর ক্লাসগুলি মাঙ্কিপ্যাচ করতে পারেন। এটি দেখতে কেমন হতে পারে তা এখানে:
class Fixnum
def exception
RuntimeError.new("I'm number: #{ self }")
end
end
raise 42
# ...results in raise_number.rb:7:in `<main>': I'm number: 42 (RuntimeError)
এটি একটি ঝরঝরে পার্টি কৌশল, কিন্তু বাস্তব জীবনে এটি কখনও কার্যকর হতে পারে? এই কৌশলটির জন্য আমি যে প্রধান ব্যবহারিক প্রয়োগটি দেখতে পাচ্ছি তা হল একটি ব্যতিক্রম তৈরি করার জন্য প্রয়োজনীয় যুক্তিটিকে আলাদা করা যা ব্যতিক্রম বাড়ানোর সিদ্ধান্ত নেয়। এটি অবশ্যই একটি প্রান্ত কেস একটি বিট. কিন্তু দেখা যাক সেটা কেমন হতে পারে।
একটি সম্ভবত ব্যবহারিক উদাহরণ
ধরুন আমি কোনো ধরনের IO থেকে ডেটার একটি লাইন পড়তে চাই। এটি নেটওয়ার্ক আইও হতে পারে, এটি একটি ফাইল হতে পারে। এটা আসলে কোন ব্যাপার না. আমি শুধু ডেটা পড়তে চাই এবং দেখতে চাই এটা বৈধ কিনা।
আমি যে ডেটা পড়ি তা বৈধ না হলে, আমি একটি ব্যতিক্রম বাড়াতে চাই। কিন্তু ব্যতিক্রম ইনপুট অনুযায়ী করা প্রয়োজন. একটি নেটওয়ার্ক সংযোগে একটি স্থানীয় ফাইলের চেয়ে আলাদা ডিবাগ তথ্য থাকতে হবে৷ আমি প্রতিটি ধরণের ইনপুট ক্লাসের জন্য কাস্টম ব্যতিক্রম পদ্ধতি প্রদান করে এটি করতে পারি। এখানে কিছু ছদ্ম-রুবি দেখায় যে এটি দেখতে কেমন হতে পারে৷
৷# These three classes represent different kinds of IO with different exceptions.
class NetworkConnection
...
def exception
NetworkConnectionError.new(url: url, ...)
end
end
class LocalFile
...
def exception
FileError.new(path: path, ...)
end
end
class UnixPipe
...
def exception
PipeError.new(...)
end
end
def read_all(*items)
items.each do |item|
if item.readline != "foo"
# We raise the item, which causes the appropriate exception class to be used.
raise item
end
end
end
read_all(NetworkConnection.new(url: "example.com"), LocalFile.new("/something"), UnixPipe.new)