Awesome print হলো একটি সুন্দর জেম যা irb এবং pry-এ আপনার আউটপুট ফরম্যাট করে इसे আরও পঠনযোগ্য করে। উদাহরণস্বরূপ… awesome_print দিয়ে একটি হ্যাশ ডিসপ্লে করলে এরা এমন দেখে:

কিন্তু এটি কীভাবে কাজ করে?
আসুন সোর্স কোডে এক নজর দিয়ে বের করি!“সত্য শুধু একটি জায়গায় পাওয়া যায়: কোডে।” ― রবার্ট সি. মার্টিন
অ্যAwsome প্রিন্টিং
আমি একটি কোড রিডিং সেশন একটি কুইক ওভারভিউ দিয়ে শুরু করি প্রজেক্ট স্ট্রাকচারের (ফাইল ও ফোল্ডার), তারপর আমি একটি প্রশ্ন করি আমার এক্সপ্লোরেশন ফোকাস করার জন্য। প্রথম প্রশ্ন যা আমার মনে পড়ল: awesome_print pry-এর আউটপুট কীভাবে পরিবর্তন করে? এখন আমি আমার ডিটেক্টিভ হ্যাট পরে এবং একটি হাইপোথিসিস বানাই: "এই জেমটি $stdout-কে রিপ্লেস করতে পারে যাতে এটি pry-এর আউটপুট ক্যাপচার করে এবং তারপর এটাকে প্রিটি বানাতে পারে।" কিন্তু এই ইমপ্লিমেন্টেশন আপনাকে আউটপুট কাস্টোমাইজ করতে দিবে না, যেমন pretty_print (রুবির স্ট্যান্ডার্ড লাইব্রেরি থেকে) করে। בנוסף, আমাদের কোড পার্স বা এভাল করতে হতো, ভালো আইডিয়া নয়! পরবর্তী: আমি দেখলাম এই জেমটি কীভাবে লোড হয়। এটি আমাদের কোডে একটি এন্ট্রি পয়েন্ট দেবে।
Awesome Print লোড করা
awesome_print pry-এ লোড করতে আপনাকে করতে হবে:
require 'awesome_print' AwesomePrint.pry!
এখন আমরা খুঁজতে চাই pry! কোথায় ডিফাইন করা হয়েছে। আমি Atom-এ "search in directory" ফিচারটি ব্যবহার করলাম এটি খুঁজে বের করতে। কোডটি এখানে:
def pry!
Pry.print = proc { |output, value| output.puts value.ai }
if defined?(Pry)
end
লাগছে Pry আপনাকে এর আউটপুট মডিফাই করতে দেয় print-এর ভ্যালু সেট করে। তাই এটা আমাদের "কোথায় থেকে শুরু করব" প্রশ্নের উত্তর দিয়েছে 🙂
এই proc দুটি আর্গুমেন্ট নেয়:এই "proc" জিনিস সম্পর্কে আরও জানতে চান? "The Ultimate Guide to Blocks, Procs & Lambdas" পড়ুন। এটি আমার Ruby Deep Dive বইর একটি স্যামপল চ্যাপ্টার।
- output
- value
এবং সেগুলোর ওপর দুটি মেথড কল করে। পরবর্তী প্রশ্ন: এই ai মেথডটি কী? এটি Kernel মডিউলে ডিফাইন করা একটি মেথড:
def ai(options = {})
ap = AwesomePrint::Inspector.new(options)
awesome = ap.awesome(self)
if options[:html]
awesome = "</pre>#{awesome}</pre>"
end
awesome = awesome.html_safe if defined? ActiveSupport
end
awesome
end
alias :awesome_inspect :ai
কারণ সব অবজেক্ট ডিফল্টভাবে Kernel ইনক্লুড করে, সেগুলোতে এই ai মেথডটি উপলব্ধ থাকবে। এখন আসুন একটু গভীরে যাই এবং দেখি এই Inspector ক্লাস কীভাবে কাজ করে।
Inspector ক্লাস
inspector.rb খোলার সাথে সাথে আমরা initialize মেথডের ভেতরে একটি বিশাল অপশন হ্যাশ পাই। এখানে এর কিছু অংশ:
@options = {
indent: 4, # Number of spaces for indenting.
index: true, # Display array indices.
html: false, # Use ANSI color codes rather than HTML.
multiline: true, # Display in multiple lines.
# ...
}
এর পর আমরা এই কোডটি পাই:
@formatter = AwesomePrint::Formatter.new(self) @indentator = AwesomePrint::Indentator.new(@options[:indent].abs) Thread.current[AP] ||= []
তবে এটা ফরম্যাটিং এবং কোডের ইন্ডেন্টেশন হ্যান্ডেল করার জন্য দুটি অবজেক্ট সেটআপ করছে। কিন্তু এই Thread.current জিনিসটি কী? এটি আপনাকে করেন্ট থ্রেডের অ্যাক্সেস দেয়। আপনি আপনার অ্যাপ্লিকেশনে থ্রেড ব্যবহার না করলেও আপনার একটি থ্রেড থাকবে, "মেইন" থ্রেড। এই AP কনস্ট্যান্টটি শুধু একটি কনস্ট্যান্ট যা inspector.rb-র টপে ডিফাইন করা আছে:
AP = :__awesome_print__তাহলে এখানে কী হচ্ছে? Awesome print
Thread.current এবং __awesome_print__ কী ব্যবহার করে কিছু ডেটা সংরক্ষণ করছে যা শুধু করেন্ট থ্রেডে উপলব্ধ। এটি মাল্টি-থ্রেডিং-এ সমস্যা এড়াতে ব্যবহৃত হয়।
অ্যAwsome ফরম্যাটিং
আসুন আউটপুট ফরম্যাটিং কোডটি দেখি, যা AwesomePrint::Formatter ক্লাসের ভেতরে হয়। এই পদ্ধতিতে ইনস্পেক্টর (ai মেথড দিয়ে তৈরি অবজেক্ট) format মেথড কল করবে।
def unnested(object) @formatter.format(object, printable(object)) endতারপর
Formatter ক্লাসের এই format মেথডটি এই টাইপের অবজেক্টের সাথে নিবটা করার সেরা পদ্ধতি খুঁজে বের করবে এবং মেটা-প্রোগ্রামিং ব্যবহার করে আরেকটি মেথড কল করবে। মেথডটি এখানে:
def format(object, type = nil)
core_class = cast(object, type)
awesome = if core_class != :self
send(:"awesome_#{core_class}", object) # Core formatters.
else
awesome_self(object, type) # Catch all that falls back to object.inspect.
end
awesome
end
এই Formatter ক্লাস বুঝতে আমাদের cast মেথডটিও দেখতে হবে:
def cast(object, type) CORE.grep(type)[0] || :self end
CORE কনস্ট্যান্টটি একটি সিম্বল অ্যারে যা কোর রুবি ক্লাসগুলোকে প্রতীক করে এবং :self হলো একটি সিম্বল যা এখানে "নট ফাউন্ড" বোঝায় (শুধু এই উদাহরণে, রুবি সাধারণত নয়)। CORE = [:array, :bigdecimal, :class, :dir, :file, :hash, :method, :rational, :set, :struct, :unboundmethod]হতে যাচ্ছে এটা: ফরম্যাট করা হচ্ছে অবজেক্টটি যদি "কোর ক্লাস" লিস্টে থাকে তবে এটি একটি স্পেশালাইজড ফরম্যাট পাবে। অন্যথায়, এটি একটি জেনেরিক ফরম্যাট পাবে। স্পেশালাইজড ফরম্যাটারগুলো
lib/awesome_print/formatters/ ডিরেক্টরিতে ডিফাইন করা থাকে এবং এতে Array, Hash এবং Class এর মত জিনিসগুলো থাকে। উদাহরণস্বরূপ, ক্লাসের জন্য ফরম্যাটার মেথডটি এখানে: def format
superclass = klass.superclass
if superclass
colorize("#{klass.inspect} < #{superclass}", :class)
else
colorize(klass.inspect, :class)
end
end আপনি চাইলে আপনার নিজস্ব ফরম্যাটারও লিখতে পারেন।
সারসংক্ষেপ
আপনি Awesome Print জেম সম্পর্কে শিখলেন, যা আপনাকে অ্যারে ও হ্যাশের মত অবজেক্টগুলো একটি সুন্দরভাবে ডিসপ্লে করতে দেয়। আশা করি আপনি এটি উপভোগ করেছেন এবং কিছু নতুন শিখলেন! অনুগ্রহ করে এই পোস্টটি আপনার প্রিয় সোশ্যাল নেটওয়ার্কে শেয়ার করুন যাতে আরও মানুষ শিখতে পারে 🙂