আপনি কি জানেন যে রুবি আপনার স্ক্রিপ্টকে ডেটার উৎস হিসাবে নিজস্ব সোর্স ফাইল ব্যবহার করার জন্য একটি উপায় প্রদান করে? এটি একটি ঝরঝরে কৌশল যা এক-অফ স্ক্রিপ্ট এবং ধারণার প্রমাণ লেখার সময় আপনাকে কিছু সময় বাঁচাতে পারে। আসুন এটি পরীক্ষা করে দেখি!
ডেটা এবং END
নীচের উদাহরণে, আমি __END__
নামে একটি মজার কীওয়ার্ড ব্যবহার করছি . নিচের সবকিছু __END__
রুবি দোভাষী দ্বারা উপেক্ষা করা হবে। কিন্তু আরো মজার বিষয় হল, রুবি আপনাকে DATA
নামে একটি IO অবজেক্ট প্রদান করে , যা আপনাকে __END__
নীচের সবকিছু পড়তে দেয় ঠিক যেমন আপনি অন্য কোনো ফাইল থেকে পড়তে পারেন।
নিম্নলিখিত উদাহরণে, আমরা প্রতিটি লাইনের উপর পুনরাবৃত্তি করি এবং এটি মুদ্রণ করি।
DATA.each_line do |line|
puts line
end
__END__
Doom
Quake
Diablo
এই কৌশলটির আমার প্রিয় ব্যবহারিক উদাহরণ DATA
ব্যবহার করে একটি ERB টেমপ্লেট ধারণ করতে। এটি YAML, CSV ইত্যাদির সাথেও কাজ করে। এম
require 'erb'
time = Time.now
renderer = ERB.new(DATA.read)
puts renderer.result()
__END__
The current time is <%= time %>.
আপনি আসলে DATA
ব্যবহার করতে পারেন __END__
এর উপরের বিষয়বস্তু পড়তে কীওয়ার্ড কারণ DATA
আসলে পুরো সোর্স ফাইলের একটি পয়েন্টার, __END__
এ দ্রুত ফরোয়ার্ড করা হয় কীওয়ার্ড আপনি এটি দেখতে পারেন যদি আপনি এটি প্রিন্ট করার আগে IO বস্তুটিকে রিওয়াইন্ড করেন। নীচের উদাহরণটি সম্পূর্ণ উৎস ফাইলটি প্রিন্ট করে।
DATA.rewind
puts DATA.read # prints the entire source file
__END__
meh
মাল্টিপল-ফাইল ডেলিমা
এই কৌশলটির একটি বড় নেতিবাচক দিক হল যে এটি শুধুমাত্র তখনই কাজ করে যখন আপনার স্ক্রিপ্ট একটি একক সোর্স ফাইলের সাথে ফিট করে এবং আপনি ফাইলটি অন্তর্ভুক্ত করার পরিবর্তে সরাসরি চালাচ্ছেন৷
নীচের উদাহরণে, আমি দুটি ফাইল পেয়েছি, প্রতিটিতে তাদের নিজস্ব __END__
অধ্যায়. তবে শুধুমাত্র একটি DATA
থাকতে পারে বিশ্বব্যাপী তাই __END__
দ্বিতীয় ফাইলের বিভাগটি অ্যাক্সেসযোগ্য নয়।
# first.rb
require "./second"
puts "First file\n----------------------"
puts DATA.read
print_second_data()
__END__
First end clause
# second.rb
def print_second_data
puts "Second file\n----------------------"
puts DATA.read # Won't output anything, since first.rb read the entire file
end
__END__
Second end clause
snhorne ~/tmp $ ruby first.rb
First file
----------------------
First end clause
Second file
----------------------
একাধিক ফাইলের জন্য একটি কাজ
সিনাত্রার একটি দুর্দান্ত বৈশিষ্ট্য রয়েছে যা আপনাকে __END__
এর পরে রেখে আপনার অ্যাপগুলিতে একাধিক ইনলাইন টেমপ্লেট যুক্ত করতে দেয়। বিবৃতি এটা এই মত দেখায়:
# This code is from the Sinatra docs at https://www.sinatrarb.com/intro.html
require 'sinatra'
get '/' do
haml :index
end
__END__
@@ layout
%html
= yield
@@ index
%div.title Hello world.
কিন্তু সিনাত্রা ঠিক কিভাবে এটা করতে পারে? সব পরে, আপনার অ্যাপ্লিকেশন সম্ভবত রাক দ্বারা লোড করা যাচ্ছে. আপনি ruby myapp.rb
চালাতে যাচ্ছেন না উৎপাদন! তারা অবশ্যই DATA
ব্যবহার করার একটি উপায় বের করেছে একাধিক ফাইল সহ।
যদিও, আপনি যদি সিনাত্রার উত্সে একটু খনন করেন, আপনি দেখতে পাবেন যে তারা প্রতারণা করছে। তারা DATA
ব্যবহার করছে না মোটেও পরিবর্তে তারা নীচের কোডের অনুরূপ কিছু করছে।
# I'm paraphrasing. See the original at https://github.com/sinatra/sinatra/blob/master/lib/sinatra/base.rb#L1284
app, data = File.read(__FILE__).split(/^__END__$/, 2)
এটি আসলে একটু বেশি জটিল, কারণ তারা __FILE__
পড়তে চায় না . যে শুধু sinatra/base.rb ফাইল হবে. পরিবর্তে তারা ফাইলের বিষয়বস্তু পেতে চায় যা একটি ফাংশন আহ্বান করেছে। তারা কলারের ফলাফল পার্স করে এটি পায়৷
কলার ফাংশন আপনাকে বলবে যে বর্তমানে চলমান ফাংশনটি কোথায় চালু করা হয়েছে। এখানে একটি দ্রুত উদাহরণ:
def some_method
puts caller
end
some_method # => caller.rb:5:in `<main>'
এখন সেখান থেকে ফাইলের নাম বের করে আনা এবং সেই ফাইলের জন্য ডেটার সমতুল্য কিছু বের করা খুবই সহজ ব্যাপার।
def get_caller_data
puts File.read(caller.first.split(":").first).split("__END__", 2).last
end
এটি ভালোর জন্য ব্যবহার করুন, মন্দ নয়
আশা করি এটা স্পষ্ট যে এই ধরনের কৌশলগুলি এমন কিছু নয় যা আপনি প্রতিদিন ব্যবহার করতে চান। তারা ঠিক পরিষ্কার, রক্ষণাবেক্ষণযোগ্য বড় কোড বেসের জন্য তৈরি করে না।
তবে মাঝে মাঝে আপনার দ্রুত এবং নোংরা কিছুর প্রয়োজন হয়, হয় এক-অফ ইউটিলিটি স্ক্রিপ্টের জন্য বা ধারণার প্রমাণের জন্য। সেক্ষেত্রে, DATA
এবং __END__
বেশ উপকারী হতে পারে।