Rails 4.2 ঘোষণায় আসন্ন Rails 5 সম্পর্কে কিছু আকর্ষণীয় খবর ছিল:এটি সম্ভবত রুবি 2.2 এর প্রয়োজন হতে চলেছে। যেটি Ruby 2 থেকে সমস্ত ভাল জিনিসের সুবিধা নেওয়ার জন্য এটিকে প্রথম রেল সংস্করণে পরিণত করবে৷
পোস্টে আবর্জনা সংগৃহীত প্রতীক এবং কীওয়ার্ড আর্গুমেন্ট উল্লেখ করা হয়েছে। কিন্তু আমার কাছে, সবচেয়ে আকর্ষণীয় রুবি 2 বৈশিষ্ট্যগুলির মধ্যে একটি হল মডিউল#প্রেপেন্ড৷
৷ alias_method_chain
এর ভাল (এবং খারাপ)
যখন আমি প্রথম Rails শিখি, alias_method_chain
সম্পূর্ণরূপে আমার মন উড়িয়ে. এটা সত্যিই দেখিয়েছে যে রুবি কতটা নমনীয় হতে পারে।
কোডের একটি মাত্র লাইন দিয়ে, আপনি একটি পদ্ধতির কাজ করার পদ্ধতি সম্পূর্ণরূপে পরিবর্তন করতে পারেন৷৷ আপনি যে কোডটি চেয়েছিলেন তা যুক্ত করতে আপনাকে আর লাইব্রেরিগুলিকে হ্যাক করার দরকার নেই, আপনি কেবল এটিকে ফ্লাইতে যুক্ত করতে পারেন। alias_method_chain
আমার প্রথম প্যাচগুলি রত্নগুলির দিকে নিয়ে গিয়েছিল, যা আমার প্রথম পুল অনুরোধের দিকে পরিচালিত করেছিল, যা আমার প্রথম ওপেন সোর্স অবদানের দিকে পরিচালিত করেছিল৷
কিন্তু ঠিক বানর প্যাচিংয়ের মতো, alias_method_chain
অত্যধিক ব্যবহার করা হয়েছে, এবং এর সমস্যাগুলি স্পষ্ট হতে শুরু করেছে:
- এটি যে পদ্ধতির নাম তৈরি করে তা বিভ্রান্তিকর, যা ত্রুটিগুলি খুঁজে বের করা এবং ডিবাগ করা কঠিন করে তোলে৷ উদাহরণস্বরূপ:
class Person
def greeting
"Hello"
end
end
module GreetingWithExcitement
def self.included(base)
base.class_eval do
alias_method_chain :greeting, :excitement
end
end
def greeting_with_excitement
"#{greeting_without_excitement}!!!!!"
end
end
Person.send(:include, GreetingWithExcitement)
আপনার যদি Person#greeting
-এ কোনো ত্রুটি থাকে , ব্যাকট্রেস আপনাকে বলবে যে একটি ত্রুটি আসলেই ঘটেছে Person#greeting_without_excitement
. কিন্তু যেখানে এই পদ্ধতি এমনকি সংজ্ঞায়িত করা হয়? আমি এটা কোথাও দেখতে পাচ্ছি না। আপনি কিভাবে জানেন কোন greeting
পদ্ধতি কি এতে বাগ আছে? এবং পদ্ধতির নামগুলি আরও বেশি বিভ্রান্তিকর হয়ে উঠবে যত বেশি আপনি চেইন করবেন।
-
যদি আপনি
alias_method_chain
কল করেন একই ক্লাসে একই প্যারামিটারের সাথে দুবার, আপনি একটি স্ট্যাক ওভারফ্লো করতে পারেন। (আপনি কি দেখতে পাচ্ছেন কেন?) এটি সাধারণত ঘটে না, যতক্ষণ না আপনারrequire
তারা কোন পাথ ব্যবহার করে সে সম্পর্কে বিবৃতিগুলি সামঞ্জস্যপূর্ণ। কিন্তু এটি অত্যন্ত বিরক্তিকর যদি আপনি ঘন ঘন একটি রেল কনসোলে কোড পেস্ট করেন। -
এবং বাকি জিনিসগুলি Yehuda Katz-এর ব্লগ পোস্ট দ্বারা বর্ণিত৷৷ এই পোস্টটি অনেক Rails devsকে
alias_method_chain
পরিত্যাগ করতে রাজি করেছে মডিউল উত্তরাধিকারের পক্ষে।
তাহলে, কেন এটি এখনও ব্যবহার করা হয়?
আপনি বেশিরভাগ alias_method_chain
প্রতিস্থাপন করতে পারেন একটি মডিউলে সেই পদ্ধতিগুলিকে ওভাররাইড করে এবং সেই মডিউলগুলিকে আপনার চাইল্ড ক্লাসে অন্তর্ভুক্ত করে৷ কিন্তু এটি শুধুমাত্র তখনই কাজ করে যখন আপনি আপনার সুপারক্লাসকে ওভাররাইড করতে চান, আপনার ক্লাসকে নয়। সেটি হল:
class ParentClass
def log
puts "In parent"
end
end
class ChildClass < ParentClass
def log
puts "In child"
super
end
def log_with_extra_message
puts "In child, with extra message"
log_without_extra_message
end
alias_method_chain :log, :extra_message
end
আপনি যদি ChildClass.new.log
চালান , আপনি দেখতে পাবেন:
In child, with extra message
In child
In parent
যদি আপনি alias_method_chain
এর পরিবর্তে মডিউল ব্যবহার করার চেষ্টা করেন , আপনি আউটপুট পেতে পারেন:
In child
In child, with extra message
In parent
কিন্তু আপনি পারবেন না log
পরিবর্তন না করেই আসল আউটপুট মেলে ChildClass
-এ পদ্ধতি . রুবি উত্তরাধিকার সেভাবে কাজ করে না। আচ্ছা, এটা হয়নি।
রুবি 2.0 এ কি পরিবর্তন হয়েছে?
Ruby 2.0 পর্যন্ত, নীচে কোড যোগ করার কোন উপায় ছিল না একটি শ্রেণী, শুধুমাত্র এটির উপরে। কিন্তু prepend
দিয়ে , আপনি একটি মডিউল থেকে একটি পদ্ধতি সহ একটি ক্লাসে একটি পদ্ধতিকে ওভাররাইড করতে পারেন এবং তারপরও super
দিয়ে ক্লাসের বাস্তবায়ন অ্যাক্সেস করতে পারেন . সুতরাং, আমাদের শেষ উদাহরণ ব্যবহার করে, আমরা এর সাথে মূল আউটপুট পেতে পারি:
class ParentClass
def log
puts "In parent"
end
end
module ExtraMessageLogging
def log
puts "In child, with extra message"
super
end
end
class ChildClass < ParentClass
prepend ExtraMessageLogging
def log
puts "In child"
super
end
end
In child, with extra message
In child
In parent
পারফেক্ট।
যদি prepend
আপনার মাথার চারপাশে মোড়ানো এখনও কঠিন, এটিকে এরকম কিছু করার মত মনে করুন:
class NewChildClass < ChildClass
include ExtraMessageLogging
end
ChildClass = NewChildClass
ব্যতীত এটি আপনার ক্লাসের নামগুলির সাথে বিশৃঙ্খলা করবে না এবং এটি ইতিমধ্যে বিদ্যমান বস্তুগুলিকে প্রভাবিত করে৷
৷(হ্যাঁ, আপনি রুবিতে ক্লাসের নাম পুনরায় বরাদ্দ করতে পারেন। না, এটি সম্ভবত একটি দুর্দান্ত ধারণা নয়।)
রেলের জন্য এর মানে কি?
সুতরাং, alias_method_chain
ব্যবহার করার শেষ অজুহাত রুবি 2.0 এ চলে গেছে। আমরা alias_method_chain
এর কয়েকটি অবশিষ্ট উদাহরণের একটি নিতে পারি রেলে:
require 'active_support/core_ext/module/aliasing'
class Range #:nodoc:
def each_with_time_with_zone(&block)
ensure_iteration_allowed
each_without_time_with_zone(&block)
end
alias_method_chain :each, :time_with_zone
def step_with_time_with_zone(n = 1, &block)
ensure_iteration_allowed
step_without_time_with_zone(n, &block)
end
alias_method_chain :step, :time_with_zone
private
def ensure_iteration_allowed
if first.is_a?(Time)
raise TypeError, "can't iterate from #{first.class}"
end
end
end
এবং এর পরিবর্তে একটি মডিউল দিয়ে প্রতিস্থাপন করুন:
require 'active_support/core_ext/module/aliasing'
module RangeWithTimeWithZoneSupport #:nodoc:
def each(&block)
ensure_iteration_allowed
super(&block)
end
def step(n = 1, &block)
ensure_iteration_allowed
super(n, &block)
end
private
def ensure_iteration_allowed
if first.is_a?(Time)
raise TypeError, "can't iterate from #{first.class}"
end
end
end
Range.send(:prepend, RangeSupportingTimeWithZone)
এটি পরিষ্কার, Range#each
নাম পরিবর্তন করা হয় না, এবং ensure_iteration_allowed
বানর-প্যাচ করা হয় না।
উত্তরাধিকার ব্যবহার করুন, প্যাচ নয়
রুবি আপনাকে এক টন নমনীয়তা দেয় এবং এটি আমার পছন্দের একটি কারণ। তবে এটিতে একটি শক্তিশালী অবজেক্ট মডেলও রয়েছে। সুতরাং আপনি যখন নিজের কোড ইনজেক্ট করতে চান, তখন এটি হ্যাক করার আগে মডিউল এবং উত্তরাধিকারের দিকে ঝুঁকে পড়ার চেষ্টা করুন৷ আপনার কোড বোঝা এবং ডিবাগ করা অনেক সহজ হবে, এবং আপনি alias_method_chain
এর মত কিছুর পার্শ্বপ্রতিক্রিয়া সনাক্ত করতে কঠিন কিছু এড়াতে পারবেন। .
alias_method_chain
আমি রেলে চালু করা সেরা পদ্ধতিগুলির মধ্যে একটি। তবে এর দিনগুলি গণনা করা হয়েছে। আমরা এটিকে ছাড়িয়ে গেছি। এবং এটি চলে গেলে আমি এটি মিস করব না।