আপনার ক্যারি-অন লাগেজটি ক্লাচ করুন, কারণ আজ আমরা পূর্বপুরুষের চেইন পর্যন্ত সমস্ত পথ ভ্রমণ করব। আমরা একটি মেথড কল ফলো করব এবং দেখব কিভাবে এটি চেইনের উপরে যায় এবং সেইসাথে মেথডটি অনুপস্থিত থাকলে কি হবে তা খুঁজে বের করব। এবং যেহেতু আমরা আগুন নিয়ে খেলতে ভালবাসি, তাই আমরা সেখানে থামব না বরং আগুন নিয়ে খেলা চালিয়ে যাব BasicObject#method_missing ওভাররাইড করছে . আপনি যদি মনোযোগ দেন, তাহলে আমরা এটিকে ব্যবহারিক উদাহরণেও ব্যবহার করতে পারি। যদিও কোন গ্যারান্টি নেই। চলুন!
পূর্বপুরুষ চেইন
রুবিতে পূর্বপুরুষ চেইনের মৌলিক নিয়মগুলি দিয়ে শুরু করা যাক:
- রুবি শুধুমাত্র একক উত্তরাধিকার সমর্থন করে
- এটি একটি বস্তুকে মডিউলের একটি সেট অন্তর্ভুক্ত করার অনুমতি দেয়
রুবিতে, পূর্বপুরুষ শৃঙ্খলটি একটি প্রদত্ত শ্রেণীর জন্য উত্তরাধিকারসূত্রে প্রাপ্ত সমস্ত শ্রেণী এবং মডিউলগুলির ট্রাভার্সালের সমন্বয়ে গঠিত।
রুবিতে পূর্বপুরুষের চেইন কীভাবে পরিচালনা করা হয় তা দেখানোর জন্য আসুন একটি উদাহরণ দেখি।
module Auth end
module Session end
module Iterable end
class Collection
prepend Iterable
end
class Users < Collection
prepend Session
include Auth
end
p Users.ancestors উত্পাদন করে:
[
Session, Users, Auth, # Users
Iterable, Collection, # Collection
Object, Kernel, BasicObject # Ruby Object Model
]
প্রথমে, আমরা ancestors বলি প্রদত্ত ক্লাসের পূর্বপুরুষ চেইন অ্যাক্সেস করার জন্য ক্লাস পদ্ধতি।
আমরা দেখতে পাচ্ছি যে Users.ancestors কে কল করা হয়েছে ক্রমানুসারে ক্লাস এবং মডিউলগুলির একটি অ্যারে প্রদান করে:
-
Users-এর পূর্বে লেখা মডিউল -
Usersক্লাস -
Usersক্লাস' অন্তর্ভুক্ত মডিউল -
Collectionক্লাসের প্রিপেন্ডেড মডিউলগুলো—ব্যবহারকারীদের সরাসরি অভিভাবক হিসেবে -
Collectionক্লাস -
Collectionক্লাস’ অন্তর্ভুক্ত মডিউল—কোনটিই নয় -
Objectক্লাস—‘যেকোনো শ্রেণীর ডিফল্ট উত্তরাধিকার -
Kernelমডিউল—Object-এ অন্তর্ভুক্ত এবং হোল্ডিং মূল পদ্ধতি -
BasicObjectক্লাস—রুবিতে রুট ক্লাস
সুতরাং, প্রদত্ত ট্রাভার্সড ক্লাস বা মডিউলের উপস্থিতির ক্রম সর্বদা নিম্নরূপ:
- প্রিপেন্ডেড মডিউলগুলি
- শ্রেণী বা মডিউল
- এর অন্তর্ভুক্ত মডিউলগুলি
পূর্বপুরুষ চেইনটি প্রধানত রুবি দ্বারা অতিক্রম করা হয় যখন একটি পদ্ধতি একটি বস্তু বা একটি শ্রেণীতে ব্যবহার করা হয়।
মেথড লুকআপ পাথ
যখন একটি বার্তা পাঠানো হয়, রুবি বার্তা গ্রহণকারীর পূর্বপুরুষের চেইনটি অতিক্রম করে এবং তাদের মধ্যে কেউ প্রদত্ত বার্তায় সাড়া দেয় কিনা তা পরীক্ষা করে।
যদি পূর্বপুরুষ চেইনের একটি প্রদত্ত শ্রেণী বা মডিউল বার্তাটির প্রতিক্রিয়া জানায়, তাহলে এই বার্তাটির সাথে যুক্ত পদ্ধতিটি কার্যকর করা হয় এবং পূর্বপুরুষ চেইন ট্রাভার্সাল বন্ধ করা হয়৷
class Collection < Array
end
Collection.ancestors # => [Collection, Array, Enumerable, Object, Kernel, BasicObject]
collection = Collection.new([:a, :b, :c])
collection.each_with_index # => :a
এখানে, collection.each_with_index বার্তাটি গণনাযোগ্য মডিউল দ্বারা গৃহীত হয়। তারপর Enumerable#each_with_index এই বার্তার জন্য পদ্ধতি বলা হয়৷
এখানে, যখন collection.each_with_index বলা হয়, রুবি পরীক্ষা করে যদি:
- সংগ্রহ
each_with_index message-এর উত্তর দেয় => না - অ্যারে
each_with_index message-এ সাড়া দেয় => না - অগণিত
each_with_index message-এর উত্তর দেয় => হ্যাঁ
সুতরাং, এখান থেকে, রুবি পূর্বপুরুষ চেইন ট্রাভার্সাল বন্ধ করে এবং এই বার্তাটির সাথে যুক্ত পদ্ধতিটিকে কল করে। আমাদের ক্ষেত্রে, Enumerable#each_with_index পদ্ধতি।
রুবিতে, এই প্রক্রিয়াটিকে মেথড লুকআপ পাথ বলা হয় .
এখন, যদি প্রদত্ত রিসিভারের পূর্বপুরুষ চেইন রচনা করে এমন কোনো ক্লাস এবং মডিউল বার্তায় সাড়া না দিলে কি হবে?
BasicObject#method_missing
সুন্দর খেলার সাথে যথেষ্ট! আসুন জিনিসগুলি ভেঙে ফেলি, বিকাশকারী শৈলী:ব্যতিক্রমগুলি ছুঁড়ে দিয়ে। আমরা একটি Collection বাস্তবায়ন করব ক্লাস এবং কল করুন একটি অজানা পদ্ধতির একটি উদাহরণে।
class Collection
end
c = Collection.new
c.search('item1') # => NoMethodError: undefined method `search` for #<Collection:0x123456890>
এখানে, Collection ক্লাস একটি search বাস্তবায়ন করে না পদ্ধতি তাই একটি NoMethodError উত্থাপিত হয়. কিন্তু এই ত্রুটি উত্থাপন কোথা থেকে আসে?
ত্রুটিটি BasicObject#method_missing-এ উত্থাপিত হয়েছে পদ্ধতি এই পদ্ধতিটি বলা হয় যখন পদ্ধতি সন্ধান পাথ শেষ পর্যন্ত প্রদত্ত বার্তার সাথে সামঞ্জস্যপূর্ণ কোনো পদ্ধতি খুঁজে পায় না।
ঠিক আছে... কিন্তু এই পদ্ধতিটি শুধুমাত্র একটি NoMethodError উত্থাপন করে . তাই আমাদের Collection এর প্রসঙ্গে পদ্ধতিটিকে ওভাররাইড করতে সক্ষম হওয়া দুর্দান্ত হবে ক্লাস।
BasicObject#method_missing ওভাররাইড করা পদ্ধতি
অনুমান কি? method_missing ওভাররাইড করা সম্পূর্ণ সূক্ষ্ম যেহেতু এই পদ্ধতিটিও মেথড লুকআপ পাথ এর মেকানিজমের অধীন . একটি সাধারণ পদ্ধতির সাথে একমাত্র পার্থক্য হল যে আমরা নিশ্চিত যে এই পদ্ধতিটি অন্তত একবার মেথড লুকআপ পাথ দ্বারা পাওয়া যাবে .
প্রকৃতপক্ষে, BasicObject class ——যেটি রুবি’-এর যেকোনো শ্রেণীর রুট ক্লাস—এই পদ্ধতির একটি ন্যূনতম সংস্করণ সংজ্ঞায়িত করে। ক্লাসিক রুবি ম্যাজিক, আর কি?
তাহলে আসুন আমাদের Collection class-এ এই পদ্ধতিটি ওভাররাইড করি :
class Collection
def initialize
@collection = {}
end
def method_missing(method_id, *args)
if method_id[-1] == '='
key = method_id[0..-2]
@collection[key.to_sym] = args.first
else
@collection[method_id]
end
end
end
collection = Collection.new
collection.obj1 = 'value1'
collection.obj2 = 'value2'
collection.obj1 # => 'value1'
collection.obj2 # => 'value2'
এখানে, Collection#method_missing @collection-এর প্রতিনিধি হিসাবে কাজ করে উদাহরণস্বরূপ পরিবর্তনশীল. প্রকৃতপক্ষে, রুবি মোটামুটিভাবে অবজেক্ট ডেলিগেশন পরিচালনা করে— س.এফ:delegate লাইব্রেরি।
অনুপস্থিত পদ্ধতি যদি সেটার পদ্ধতি হয় (collection.obj1 = 'value1' ), তারপর পদ্ধতির নাম (:obj1 ) কী এবং আর্গুমেন্ট ('value1') হিসাবে ব্যবহৃত হয় ) @collection এর মান হিসাবে হ্যাশ এন্ট্রি (@collection[:obj1] = 'value1' )।
একটি HTML ট্যাগ জেনারেটর
এখন আমরা জানি কিভাবে method_missing পদ্ধতি পর্দার আড়ালে কাজ করে, আসুন একটি পুনরুৎপাদনযোগ্য ব্যবহারের ক্ষেত্রে প্রয়োগ করি।
এখানে, লক্ষ্য হল নিম্নলিখিত ডিএসএলকে সংজ্ঞায়িত করা:
HTML.p 'hello world' # => <p>hello world</p>
HTML.div 'hello world' # => <div>hello world</div>
HTML.h1 'hello world' # => <h1>hello world</h1>
HTML.h2 'hello world' # => <h2>hello world</h2>
HTML.span 'hello world' # => <span>hello world</span>
HTML.p "hello #{HTML.b 'world'}" # => <p>hello <b>world</b></p>
এটি করতে, আমরা HTML.method_missing বাস্তবায়ন করতে যাচ্ছি পদ্ধতি যাতে প্রতিটি HTML ট্যাগের জন্য একটি পদ্ধতি সংজ্ঞায়িত করা না হয়।
প্রথমে, আমরা একটি HTML সংজ্ঞায়িত করি মডিউল তারপর আমরা একটি method_missing সংজ্ঞায়িত করি এই মডিউলে ক্লাস পদ্ধতি:
module HTML
def HTML.method_missing(method_id, *args, &block)
"<#{method_id}>#{args.first}</#{method_id}>"
end
end
আমাদের পদ্ধতি অনুপস্থিত method_id ব্যবহার করে একটি HTML ট্যাগ তৈরি করবে ——:div HTML.div এ কল করার জন্য , উদাহরণস্বরূপ।
মনে রাখবেন যে ক্লাস পদ্ধতিগুলিও মেথড লুকআপ পাথের বিষয়।
আমরা আমাদের HTML ট্যাগ জেনারেটরকে এর দ্বারা উন্নত করতে পারি:
- নেস্টেড ট্যাগগুলি পরিচালনা করতে ব্লক আর্গুমেন্ট ব্যবহার করে
- একক ট্যাগ পরিচালনা করা——
<br/>উদাহরণস্বরূপ
কিন্তু মনে রাখবেন যে কোডের কয়েকটি লাইন দিয়ে, আমরা প্রচুর পরিমাণে HTML ট্যাগ তৈরি করতে সক্ষম।
সুতরাং, সংক্ষেপে:
method_missing ডিএসএল তৈরি করার জন্য এটি একটি ভাল এন্ট্রি পয়েন্ট যেখানে বেশিরভাগ কমান্ড চিহ্নিত প্যাটার্নের একটি সেট ভাগ করবে।
উপসংহার
আমরা রুবিতে পূর্বপুরুষ শৃঙ্খল পর্যন্ত গিয়েছিলাম এবং BasicObject#method_missing এ ঢুকেছিলাম . BasicObject#method_missing এটি রুবি হুক পদ্ধতির অংশ . এটি তাদের জীবনচক্রের কিছু নির্দিষ্ট মুহুর্তে বস্তুর সাথে যোগাযোগ করতে ব্যবহৃত হয়। অন্যান্য রুবি হুক পদ্ধতির মতো , এই হুক পদ্ধতি সাবধানে ব্যবহার করতে হবে. এবং সাবধানতার সাথে, আমরা বলতে চাচ্ছি যে এটি কখনই রুবি অবজেক্ট মডেলের আচরণগুলিকে সংশোধন করবে না —যখন আপনি এটি নিয়ে খেলছেন বা এটিতে একটি ব্লগ পোস্ট লিখছেন;-)
ভয়লা!