আমরা Honeybadger-এ একটি মাইলফলক পেয়েছি। আমাদের সেলস পেজগুলো আর আমাদের মেইন রেইলস অ্যাপের অংশ নয়। এটি আমার উইশ লিস্টে سالها থেকে ছিল, কিন্তু একজendom প্রায়োরিটি ছিল না।
এই মাইগ্রেশনের অংশ হিসেবে, আমি নিজেকে URI.join ব্যবহার করে নির্দিষ্ট রিডাইরেক্ট লিংক কনস্ট্রাক্ট করতে পেলাম। কিন্তু আমি দ্রুত একটি সমস্যায় পড়লাম। URI.join আমার এক্সপেক্টেশন অনুযায়ী আচরণ করল না।
আমি এক্সপেক্ট করছিলাম এটি একসাথে পাথ ফ্র্যাগমেন্টগুলোকে স্ট্রিং করে দেবে এইরকম:
# আমি যা এক্সপেক্ট করছিলাম। এটি হয়নি।
URI.join("https://www.honeybadger.io", "plans", "change")
# => "https://www.honeybadger.io/plans/change"
join মেথড যা করেছে সেটি অনেক স্ট্রেঞ্জ। এটি আমার পাথ ফ্র্যাগমেন্টের একটি ড্রপ করে দিল, শুধু শেষটি, "change" ব্যবহার করল।
# যা ঘটল।
URI.join("https://www.honeybadger.io", "plans", "change")
# => "https://www.honeybadger.io/change"
তাহলে কেন এটি এইরকম কাজ করে?
ভুল বোঝাপড়া
এটি বের হয় যে আমি URI.join-কে Array#join-এর একটি স্পেশালাইজড ভার্সনের মতো আচরণ করতে এক্সপেক্ট করছিলাম, URL ফ্র্যাগমেন্টগুলো নিয়ে সেগুলো কম্বাইন করে একটি পূর্ণ URL বানাতে।
এটা সেটি করে না। বড় সারপ্রাইজ।
যদি আমরা join মেথডের কোডে তাকাই, দেখব এটি শুধু সব আর্গুমেন্টের ওপর ইটারেট করে, এবং প্রতিটিতে merge কল করে।
# File uri/rfc2396_parser.rb, line 236
def join(*uris)
uris[0] = convert_to_uri(uris[0])
uris.inject :merge
end
merge মেথড দুটি জিনিস করে:
- আপনার স্ট্রিং যেমন "pages" কে একটি রিলেটিভ URI অবজেক্টে কনভার্ট করে।
- রিলেটিভ URI-কে বেস URI-র ওপর রেজলভ করার চেষ্টা করে। এটি RFC2396, Section 5.2-এ নির্দিষ্টভাবে করে।
এটা কুল, কিন্তু এটি আমার আগে বোঝানো অপ্রত্যাশিত আচরণকে কীভাবে ব্যাখ্যা করে?
URI.join("https://www.honeybadger.io", "plans", "change")
# => "https://www.honeybadger.io/change"
এটি ধাপে ধাপে দেখি। উপরের কোডটি সমতুল্য:
URI.parse("https://www.honeybadger.io/plans").merge("change")
উপরের কোডটি রিলেটিভ URI, "change" কে অ্যাবসোলিউট URI "https://www.honeybadger.io/plans" এর ওপর রেজলভ করার চেষ্টা করে।
এটি করতে, এটি RFC2396, Section 5.2.6 ফলো করে, যা বলে:
a) বেস URI-এর পাথ কম্পোনেন্টের শেষ সেগমেন্ট বাদে সব কপি হয় বাফারে। অন্য কথায়, শেষ (রাইট-মোস্ট) স্ল্যাশ ক্যারেক্টারের পরের যেকোনো ক্যারেক্টার, যদি থাকে, এক্সক্লুড করা হয়।
b) রেফারেন্সের পাথ কম্পোনেন্ট বাফার স্ট্রিংয়ের সাথে অ্যেন্ড হয়।
চলুন এখানেও খেলি:
- অ্যাবসোলিউট URL-এর ফাইনাল সেগমেন্ট বাদে সব কপি করুন। যা আমাকে দেয়
"https://www.honeybadger.io/" - রিলেটিভ পাথ অ্যেন্ড করুন, ফলাফল
"https://www.honeybadger.io/change"
বিশ্ব আবার অর্থপূর্ণ হয়ে গেল!
উপসংহার
URI.join যেকোনো পাথ ফ্র্যাগমেন্ট থেকে URL বিল্ড করার জন্য ব্যবহার করা যায়, কিন্তু এটিই সেটি করার জন্য ডিজাইন করা হয়নি। এটি কিছুটা বেশি জটিল কিছু করার জন্য ডিজাইন করা হয়েছে: RFC-এ স্পেসিফাই করা סט্যান্ডার্ড অনুযায়ী URI রিকার্সিভলি মার্জ করা।
আমার পার্সনাল প্রজেক্টের জন্য—আমাদের নতুন সেলস পেজে রিডাইরেক্টের জন্য URL বিল্ড করা—আমি শুধু Array#join ব্যবহার করলাম। :)
EDIT 8/12/2016: এই আর্টিকেল পাবলিশ করার পর আমি কয়েকটি টুইট পেলাম যেগুলো সাজেস্ট করল File.join ব্যবহার করার জন্য। এর সুবিধা হচ্ছে ডাবল স্ল্যাশ এড়ানো, অর্থাৎ /my//path কিন্তু Windows-এর মতো OS-এ ব্রেক করবে, যেখানে পাথ সেপারেটর ফরোয়ার্ড-স্ল্যাশ নয়।