কম্পিউটার

রেল 5, মডিউল#প্রিপেন্ড এবং `অ্যালিয়াস_মেথড_চেইন` এর সমাপ্তি

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 এর কয়েকটি অবশিষ্ট উদাহরণের একটি নিতে পারি রেলে:

rails/activesupport/lib/active_support/core_ext/range/each.rb
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 আমি রেলে চালু করা সেরা পদ্ধতিগুলির মধ্যে একটি। তবে এর দিনগুলি গণনা করা হয়েছে। আমরা এটিকে ছাড়িয়ে গেছি। এবং এটি চলে গেলে আমি এটি মিস করব না।


  1. উইন্ডোজ ভিস্তা সাপোর্ট শেষ করার জন্য আপনার যা জানা এবং করণীয় দরকার

  2. পাইথন এবং ম্যাটপ্লটলিব ব্যবহার করে লাইনের শেষটি কীভাবে টীকা করবেন?

  3. আমি রেল পডকাস্টে রুবিতে ছিলাম!

  4. রেল এবং ক্যারিয়ারওয়েভ দিয়ে আপলোড করা হচ্ছে