কম্পিউটার

রুবি মডিউল বাসা বাঁধার সময় এই ফাঁদগুলি এড়িয়ে চলুন

মডিউল (এবং ক্লাস) নেস্ট করা বোঝানো হয়. কোডের টুকরো যেমন ActiveRecord::RecordNotFound এত সাধারণ যে আমরা তাদের সম্পর্কে দুবার ভাবি না। কিন্তু রুবির নেস্টিং বাস্তবায়নের মধ্যে সমাহিত - এবং রেলের অটোলোড সিস্টেম - কয়েকটি ফাঁদ যা আপনার কোডকে অদ্ভুত এবং বিস্ময়কর উপায়ে ব্যর্থ করতে পারে। এই পোস্টে, আমরা এই ফাঁদের উৎপত্তি এবং কীভাবে আপনি এগুলি এড়াতে পারেন তা নিয়ে আলোচনা করব।

ধ্রুবক কি?

এই পোস্টটি মডিউল সম্পর্কে, তবে সেগুলি বোঝার জন্য আমাদের ধ্রুবকগুলি বুঝতে হবে। বেশিরভাগ ভাষায়, ধ্রুবকগুলি শুধুমাত্র সামান্য কিছু ডেটা সংরক্ষণ করতে ব্যবহৃত হয়, যেমন নীচের উদাহরণে:

# These are simple constants
MAX_RETRIES = 5
DEFAULT_LANGUAGE = "en"

কিন্তু রুবিতে, ক্লাস এবং মডিউলগুলিও ধ্রুবক। আমি এটি প্রদর্শন করার জন্য একটি ছোট উদাহরণ লিখেছি। নীচের মডিউলে তিনটি ধ্রুবক রয়েছে:একটি সংখ্যা, একটি শ্রেণি এবং একটি নেস্টেড মডিউল৷ আপনি যখন একটি নেস্টেড ক্লাস বা মডিউল অ্যাক্সেস করেন, তখন রুবি একই নিয়মগুলি ব্যবহার করে এটি খুঁজে পায় যা এটি একটি সাধারণ সংখ্যাসূচক ধ্রুবকের সাথে ব্যবহার করবে৷

module MyModule
  MY_FAVORITE_NUMBER = 7

  # Classes are constants
  class MyClass
  end

  # So are modules
  module MyEmbeddedModule
  end
end

puts MyModule.constants.inspect # => [:MY_FAVORITE_NUMBER, :MyClass, :MyEmbeddedModule]

প্রায়শই, মডিউলগুলির তাদের পিতামাতার মধ্যে সংজ্ঞায়িত ধ্রুবকগুলিতে অ্যাক্সেস থাকে। তাই আপনি এই মত কোড লিখতে পারেন:

module X
  MARCO = "polo"
  module Y
    def self.n 
      puts MARCO
    end
  end
end

X::Y.n() # => "polo"

কিন্তু আপনি ভুল হবেন যদি আপনি মনে করেন যে এই পিতামাতা/সন্তানের সম্পর্কই Y কে X-এর ধ্রুবক MARCO অ্যাক্সেস করতে দেয়৷

একটি সাধারণ সমস্যা

আমরা যদি উপরের কোডটিকে একটু ভিন্নভাবে আবার লিখি, তাহলে আশ্চর্যজনক কিছু ঘটবে। Y আর X::MARCO অ্যাক্সেস করতে পারবে না৷ এখানে কি হচ্ছে?

module A
  MARCO = "polo"
end

module A::B
  def self.n 
    puts MARCO  # => uninitialized constant A::B::MARCO (NameError)
  end
end

A::B.n()

দেখা যাচ্ছে যে সন্তানের দ্বারা পিতামাতার ধ্রুবকের "উত্তরাধিকার" পিতামাতা/সন্তানের সম্পর্কের কারণে নয়। এটা আভিধানিক. এর মানে হল যে এটি আপনার কোডের কাঠামোর উপর ভিত্তি করে, আপনার কোড যে অবজেক্ট তৈরি করছে তার কাঠামোর উপর নয়।

নেস্টিং পরিদর্শন

রুবি কীভাবে নেস্টেড ধ্রুবকগুলি অনুসন্ধান করে সে সম্পর্কে আপনি যদি আরও গভীরভাবে বুঝতে চান তবে Module.nesting চেক করা মূল্যবান। ফাংশন।

এই ফাংশনটি বস্তুর একটি অ্যারে প্রদান করে যা একটি নির্দিষ্ট সুযোগে ধ্রুবকের জন্য "অনুসন্ধান পথ" তৈরি করে। আমাদের আগের উদাহরণগুলির জন্য নেস্টিং পরীক্ষা করা যাক৷

আমাদের প্রথম উদাহরণে, আমরা দেখতে পাই যে নেস্টিং হল [A::B, A] . এর মানে হল যে যদি আমরা ধ্রুবক MARCO ব্যবহার করি, রুবি প্রথমে এটি A::B এ খুঁজবে। , এবং তারপর A-এ .

module A
  MARCO = "polo"
  module B
    def self.n 
      puts Module.nesting.inspect  # => [A::B, A]
      puts MARCO # => "polo"
    end
  end
end

দ্বিতীয় উদাহরণে, আমরা দেখতে পাচ্ছি যে নেস্টিং শুধুমাত্র A::B অন্তর্ভুক্ত করে , A নয় . যদিও B হল A এর "শিশু"৷ , আমি যেভাবে কোড লিখেছি তাতে সেগুলি নেস্টেড হিসাবে দেখায় না, তাই এই উদ্দেশ্যে তারা নাও হতে পারে৷

module A
  MARCO = "polo"
end

module A::B
  def self.n 
    puts Module.nesting.inspect  # => [A::B]
    puts MARCO # => uninitialized constant A::B::MARCO (NameError)
  end
end

রেল অটোলোড জটিলতা

আপনি কি কখনও লক্ষ্য করেছেন যে আপনি যখন রেল ব্যবহার করেন তখন আপনাকে ফাইলগুলি অন্তর্ভুক্ত করতে হবে না? আপনি যদি একটি মডেল ব্যবহার করতে চান, আপনি শুধুমাত্র এটি ব্যবহার করুন.

এটি সম্ভব কারণ রেল একটি অটোলোড সিস্টেম প্রয়োগ করে। এটি Module.const_missing ব্যবহার করে আপনি যখন লোড করা হয়নি এমন একটি ধ্রুবক উল্লেখ করার চেষ্টা করেন তখন সনাক্ত করতে। এটি তারপরে ধ্রুবক থাকা উচিত বলে বিশ্বাস করে এমন ফাইলগুলি লোড করে। এটি বেশিরভাগ সময় কাজ করে, কিন্তু একটি ধরা আছে।

রেলগুলি অনুমান করে যে একটি মডিউলে সর্বদা সবচেয়ে বড় সম্ভাব্য নেস্টিং থাকে। এটি অনুমান করে যে মডিউল A::B::C এর একটি নেস্টিং থাকবে [A::B::C, A::B, A] . যদি তা না হয় তাহলে আপনি অপ্রত্যাশিত আচরণ পাবেন।

নীচের কোডে, মডিউল B A::MARCO অ্যাক্সেস করতে সক্ষম হবে না . স্বাভাবিক রুবিতে, এটি সক্ষম হবে না কারণ এর বাসা বাঁধে [A::B]। তাই আপনি একটি ব্যতিক্রম পেতে হবে. কিন্তু রেলের অটোলোড একটি ব্যতিক্রম নিক্ষেপ করে না। পরিবর্তে, এটি A::MARCO প্রদান করে .

# a.rb
module A
  MARCO = "polo"
end

# a/b.rb
module A::B
  def self.n 
    puts MARCO # => "polo"
  end
end

# some_controller.rb
A::B.n()

উপসংহার?

এই সব অনেক চিন্তা. আমি যেখানে সম্ভব চিন্তা এড়াতে পছন্দ করি, তাই আমি মডিউল A::B থেকে দূরে থাকার চেষ্টা করি বাক্য গঠন. আমি এমন একটি কেস নিয়ে ভাবতে পারি না যেখানে আমি ইচ্ছাকৃতভাবে মডিউল নেস্টিংটি পরিচালনা করতে চাই। আপনি যদি কোন সম্পর্কে জানেন, আমি তাদের সম্পর্কে শুনতে চাই!


  1. রুবি গণনাযোগ্য মডিউলের একটি প্রাথমিক নির্দেশিকা (+ আমার প্রিয় পদ্ধতি)

  2. রুবি কেস স্টেটমেন্টের অনেক ব্যবহার

  3. Google-এ এই 12টি জিনিস অনুসন্ধান করার সময় সতর্ক থাকুন

  4. এই উইন্ডোজ রক্ষণাবেক্ষণের ভুলগুলি করা এড়িয়ে চলুন