আপনি শুনেছেন होंगे (বা নিজেই বলেছেন) যে রেলস / রুবিতে খুব বেশি ম্যাজিক আছে…
- কিন্তু সেই ধারণাটি কোথা থেকে আসে?
- রেলস ম্যাজিক আসলেই কী?
- এবং সেই ম্যাজিক দূর করার জন্য আপনি কী করতে পারেন?
আমি কী মনে করি:
যখন কিছু ম্যাজিকের মতো লাগে সেটি হলো কিছু আপনি না জানা কারণে, কিছু তথ্য অনুপস্থিত থাকে।
এটি একটা ম্যাজিক ট্রিকের মতো, আপনি যদি ট্রিকটি জানেন তবে কোনো ম্যাজিক নেই।

সফটওয়্যার ডেভেলপমেন্টে, ট্রিকগুলো জানা সমতুল্য জিনিসগুলো আসলে কীভাবে কাজ করে তা বোঝা।
একটি উদাহরণ দেখি!
এই উদাহরণটি BCrypt সম্পর্কে, একটি হ্যাশিং অ্যালগরিদম যা পাসওয়ার্ড নিরাপদে সংরক্ষণের জন্য ব্যবহৃত হয়। এটি রুবিতে bcrypt জেম দিয়ে ইমপ্লিমেন্ট করা হয়েছে।
এখানে "testing" শব্দটি হ্যাশ করার জন্য BCrypt ব্যবহার দেখানো হলো:
require 'bcrypt' BCrypt::Password.create("testing") # "$2a$10$3o.xrISG8fqKfzKqDpgKn.3cwjFV//9C9cZ7MuK5S9sNKFBivB7YG" BCrypt::Password.create("testing") # "$2a$10$BFb/e3cWuAIyelcmkfGtE.GTifXHxig4IzVbdZs9C1zSpF/Jr6c3W" BCrypt::Password.create("testing") # "$2a$10$Q952BVgM783Y4kPvwvxwC.CS2DWUX9jQuDoE6q2R041kQY0ZWPnSe" লক্ষ্য করুন প্রতিবার আলাদা হ্যাশ পাওয়া যাচ্ছে, কিন্তু আপনি যদি MD5 (না করুন!) বা SHA1 ব্যবহার করেন তবে একটি নির্দিষ্ট স্ট্রিং-এর জন্য আপনি সবসময় একই আউটপুট পাবেন।
BCrypt ভিন্নভাবে কেন আচরণ করছে?
এক সেকেন্ডে ব্যাখ্যা করব, কিন্তু আগে দেখি দুটি bcrypt হ্যাশ কীভাবে কমপেয়ার করা হয়, একটি ডাটাবেস থেকে আসে এবং অন্যটি ইউজার ইনপুট থেকে (যেমন একটি ফর্ম বা এমন কিছু)।
BCrypt::Password.new(@user.hash) == params[:password] # true
বাম দিকের অংশ (BCrypt::Password.new) হলো একটি BCrypt অবজেক্ট, যা ডাটাবেসে সংরক্ষিত হ্যাশকে প্যারামিটার হিসেবে নেয়।
ডান দিকের অংশ (params[:password]) হলো প্লেইন-টেক্সট পাসওয়ার্ড যা ইউজার লগইন করার চেষ্টা করছে।
এই কেসে আমরা ধরে নিচ্ছি সঠিক ইউজার / পাসওয়ার্ড কম্বিনেশন ব্যবহার করা হচ্ছে।
তাহলে এটি true-এ কেন ইভ্যালুয়েট হচ্ছে?
খুব সহজ, এই দুটি জিনিস জানলে বুঝতে পারবেন:
- BCrypt "সল্ট" (salt) নামে একটি জিনিস ব্যবহার করে, যা পূর্ব-গণনা করা হ্যাশের বিরুদ্ধে নিরাপত্তা বাড়ানোর জন্য একটি র্যান্ডম ভ্যালু। সল্টটি হ্যাশের ভিতরেই সংরক্ষিত থাকে।
- রুবিতে অনেক জিনিস যা সিনট্যাক্সের মতো দেখে সেগুলো আসলে মেথড। এটি ডবল ইকวালস অপারেটর (
==) এর জন্যও সত্য।
এটি জানলে আমি আপনাকে বলতে পারি BCrypt নিজস্ব == মেথড ডিফাইন করেছে, যা সল্ট ভ্যালু এক্সট্র্যাক্ট করতে জানে যাতে পাসওয়ার্ড কমপেয়ার করার সময় সেটি বিবেচনা করা যায়।
অন্য কথায়:
BCrypt#== সংরক্ষিত হ্যাশ থেকে "সল্ট" ভ্যালু নেয়।
তারপর প্লেইন-টেক্সট পাসওয়ার্ড (ইউজার ইনপুট) কে এই সল্ট ব্যবহার করে হ্যাশ করে যাতে দুটি হ্যাশ একই হয়ে যায় যদি পাসওয়ার্ডটি বৈধ হয়।
যদি আপনি সোর্স কোডে তাকান তবে এটি এরকম দেখাবে:
def ==(secret) super( BCrypt::Engine.hash_secret(secret, @salt) ) end
মনে রাখবেন super একই মেথডকে (এই কেসে ==) পেরেন্ট ক্লাসে কল করবে।
BCrypt::Password-এর পেরেন্ট ক্লাস হলো String।
সবকিছু মেথড সম্পর্কে
একটি গুরুত্বপূর্ণ জিনিস বুঝতে হবে কিছু কীওয়ার্ড এবং কিছু সিনট্যাক্স এলিমেন্ট (যেমন প্যারেনথেসিস) বাদে, সবক্লাস এবং মেথড সম্পর্কে।
আপনি যদি জানেন আপনি কোন ক্লাসের সাথে কাজ করছেন (যা আপনি class মেথড দিয়ে চেক করতে পারেন) তবে আপনি সবসময় জানতে পারবেন কোন অপারেশন (মেথড) উপলব্ধ।
কিন্তু কখনও কখনও আমাদের শুধু একটি মেথড কল থাকে অবজেক্ট ছাড়া।
এটি প্রায়শই বোঝায় মেথডটি করেন্ট ক্লাসে সংজ্ঞায়িত, কিন্তু সেটি সবসময় সত্য নয়।
উদাহরণ:
puts 123
puts কোথায় সংজ্ঞায়িত? জানিয়ে ফেলি:
method(:puts).owner # Kernel
একটি জিনিস যা বিভ্রান্তিকারী হতে পারে সেটি হলো মেটাপ্রোগ্রামিং, কারণ মেটাপ্রোগ্রামিং দিয়ে আপনি প্রোগ্রাম এক্সিকিউশনের সময় মেথড তৈরি, মডিফাই বা এমনকি সরাতে পারেন। এই জিনিসগুলো কোডকে আরও অপার্ক ও অস্পষ্ট করে।
আপনি কী মেটাপ্রোগ্রামিং মেথডগুলো উপলব্ধ এবং সেগুলো কীভাবে কাজ করে সেটি সম্পর্কে সচেতন হয়ে বিভ্রান্তি কমাতে পারেন।
সারসংক্ষেপ
আপনি শিখেছেন কীভাবে জিনিসগুলো কীভাবে কাজ করে সে সম্পর্কে গভীর বোঝাপড়া আপনাকে যেকোনো "ম্যাজিক" দূর করতে, ভালো কোড লিখতে এবং আপনাকে একটি ভালো ডেভেলপার বানাতে সাহায্য করতে পারে।
আপনি যদি আপনার রুবি স্কিল বাড়াতে চান তবে আমার বই, Ruby Deep Dive, চেক আউট করুন, যা ফান্ডামেন্টাল এবং উন্নত ধারণার মধ্যে সেতু বাঁধার জন্য ডিজাইন করা হয়েছে 🙂