Computer >> कंप्यूटर >  >> प्रोग्रामिंग >> Ruby

रेल 5, मॉड्यूल#प्रीपेन्ड, और `Alias_method_chain` . का अंत

रेल 4.2 की घोषणा में आगामी रेल 5 के बारे में कुछ दिलचस्प खबरें थीं:शायद इसके लिए रूबी 2.2 की आवश्यकता होगी। जो इसे रूबी 2 की सभी अच्छी चीजों का लाभ उठाने वाला पहला रेल संस्करण बना देगा।

पोस्ट में कचरा एकत्रित प्रतीकों और कीवर्ड तर्कों का उल्लेख किया गया है। लेकिन मेरे लिए, सबसे दिलचस्प रूबी 2 सुविधाओं में से एक है मॉड्यूल#प्रीपेन्ड।

alias_method_chain का अच्छा (और बुरा)

जब मैंने पहली बार रेल सीखा, 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 कथन संगत हैं कि वे किन रास्तों का उपयोग करते हैं। लेकिन अगर आप अक्सर रेल कंसोल में कोड पेस्ट करते हैं तो यह बहुत कष्टप्रद होता है।

  • और बाकी बातें येहुदा काट्ज के ब्लॉग पोस्ट द्वारा बताई गई हैं। इस पोस्ट ने बहुत से रेल डेवलपर्स को 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 में क्या बदला?

रूबी 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. Windows Vista समर्थन के अंत के लिए आपको क्या जानना चाहिए और क्या करना चाहिए

    क्या आप Windows Vista चलाने वाले कंप्यूटर के स्वामी हैं या उसका उपयोग करते हैं? हालांकि यह काफी पुराना ऑपरेटिंग सिस्टम बनने लगा है, फिर भी यह दैनिक जीवन की मांगों के खिलाफ अच्छा प्रदर्शन कर सकता है। जैसे, ऐसे लोग हैं जो अभी भी काम और/या खेलने के लिए विस्टा ओएस पर निर्भर हैं। दुर्भाग्य से, 11 अप्रैल

  1. पायथन और मैटप्लोटलिब का उपयोग करके लाइनों के अंत की व्याख्या कैसे करें?

    पायथन और मैटप्लोटलिब का उपयोग करके पंक्तियों के अंत की व्याख्या करने के लिए, हम निम्नलिखित कदम उठा सकते हैं - आकृति का आकार सेट करें और सबप्लॉट के बीच और आसपास पैडिंग समायोजित करें। चर को इनिशियलाइज़ करें, पंक्तियाँ , पंक्तियों की संख्या डेटा प्राप्त करने के लिए। आयताकार सारणीबद्ध डेटा में पांडा डे

  1. रेल और कैरियरवेव के साथ अपलोड करना

    यह अपलोडिंग विद रेल्स श्रृंखला का एक और लेख है। आज हम कैरियरवेव से मिलने जा रहे हैं - रेल के लिए सबसे लोकप्रिय फ़ाइल अपलोडिंग समाधानों में से एक। मुझे कैरियरवेव पसंद है क्योंकि इसे शुरू करना आसान है, इसमें बहुत सारी विशेषताएं हैं, और यह समुदाय के सदस्यों द्वारा लिखे गए दर्जनों कैसे करें लेख प्रदान क