क्या आप कभी एक मेथड को एक फंक्शन में पास करना चाहते थे जो केवल एक ब्लॉक लेता है? या यह पता लगाना चाहते थे कि आपके ऑब्जेक्ट के किस सुपरक्लास ने उस मेथड को तोड़ दिया जिसे आप कॉल करने की कोशिश कर रहे हैं?
वे चीजें method मेथड के साथ करना आसान है। इसका अच्छा उपयोग करें, और आप अपनी निर्भरताओं के बारे में जान सकते हैं, डीबगिंग के घंटों को बचा सकते हैं, और अपने कोड को उन जगहों पर पहुंचा सकते हैं जहां इसे होना चाहिए।
मेथड्स लैम्ब्डा जितने आसान
बहुत सारे रूबी मेथड्स ब्लॉक्स या लैम्ब्डा लेते हैं। लेकिन आप एक मेथड को सीधे दूसरे मेथड में पास नहीं कर सकते, जैसे आप लैम्ब्डा के साथ करेंगे। आपको पहले method का उपयोग करना होगा:
irb(main):001:0> sin_method = Math.method(:sin)
=> #<Method: Math.sin>
irb(main):002:0> (1..10).map(&sin_method)
=> [0.8414709848078965, 0.9092974268256817, 0.1411200080598672, -0.7568024953079282, -0.9589242746631385, -0.27941549819892586, 0.6569865987187891, 0.9893582466233818, 0.4121184852417566, -0.5440211108893699]
तो, यहां क्या हो रहा है?
पहली लाइन मेथड Math.sin को एक Method ऑब्जेक्ट में बदल देती है। लैम्ब्डा की तरह, `Method` ऑब्जेक्ट्स `call` का जवाब देते हैं। Method ऑब्जेक्ट्स to_proc का जवाब देते हैं (धन्यवाद, बेनोइट)। इसलिए उन्हें उन्हीं स्थानों पर उपयोग किया जा सकता है जहां आप एक लैम्ब्डा का उपयोग करेंगे:
irb(main):004:0> sin_method = -> (x) { Math.sin(x) }
=> #<Proc:0x007fe9f90a9bd8@(irb):4 (lambda)>
irb(main):005:0> (1..10).map(&sin_method)
=> [0.8414709848078965, 0.9092974268256817, 0.1411200080598672, -0.7568024953079282, -0.9589242746631385, -0.27941549819892586, 0.6569865987187891, 0.9893582466233818, 0.4121184852417566, -0.5440211108893699]
पहली लाइन पर फिर से नज़र डालें। यह कोड, एक लैम्ब्डा का उपयोग करके, पहले वाले कोड के समान ही काम करता है, जिसमें method का उपयोग किया गया था।
आपने अपने कोड को कैसे लिखा है, इस पर निर्भर करते हुए, एक Method ऑब्जेक्ट प्राप्त करना इसे लैम्ब्डा में लपेटने की तुलना में बहुत आसान हो सकता है। इसलिए जब आपको एक लैम्ब्डा की आवश्यकता हो और आपके पास केवल एक मेथड हो, तो method मेथड को याद रखें।
वह मेथड कहां से आया?
आपने अपने ऑब्जेक्ट पर एक मेथड कॉल किया, और यह कुछ ऐसा करता है जिसकी आप उम्मीद नहीं करते। शायद किसी ने इसे ओवरराइड किया या मंकी-पैच किया। आप इसका पता कैसे लगाते हैं?
आप कुछ घंटों के लिए सोर्स कोड के माध्यम से खुदाई कर सकते हैं। लेकिन Method में दो मेथड्स हैं जो चीजों को गति दे सकते हैं।
यह पता लगाने के लिए कि जिस मेथड को आप कॉल कर रहे हैं उसे किस क्लास ने परिभाषित किया है, owner का उपयोग करें:
irb(main):003:0> Task.new.method(:valid?).owner
=> ActiveRecord::Validations
जब आप थोड़ा गहरा जाना चाहते हैं और ठीक-ठीक पता लगाना चाहते हैं कि मेथड कहां परिभाषित किया गया था, तो source_location का उपयोग करें:
irb(main):004:0> Task.new.method(:valid?).source_location
=> ["/usr/local/lib/ruby/gems/2.1.0/gems/activerecord-4.2.0.beta2/lib/active_record/validations.rb", 55]
source_location एक सरणी वापस करता है। पहला तत्व वह पथ है जहां मेथड परिभाषित किया गया था, और दूसरा तत्व लाइन नंबर है। उन के साथ, आप ठीक-ठीक जानते हैं कि आगे कहां देखना है।
खुदाई किए बिना स्रोत पढ़ना
एक बार जब आप यह पता लगा लेते हैं कि मेथड कहां परिभाषित किया गया था, तो आप देखना चाह सकते हैं कि यह कैसे परिभाषित किया गया है।
Method इसे अपने आप नहीं कर सकता। लेकिन यदि आप method_source जेम इंस्टॉल करते हैं, तो आप अपने कंसोल से कई मेथड्स का सोर्स कोड देख सकते हैं:
irb(main):002:0> puts Task.new.method(:valid?).source
def valid?(context = nil)
context ||= (new_record? ? :create : :update)
output = super(context)
errors.empty? && output
end
=> nil
आप टिप्पणियों को भी देख सकते हैं:
irb(main):003:0> puts Task.new.method(:valid?).comment
# Runs all the validations within the specified context. Returns +true+ if
# no errors are found, +false+ otherwise.
#
# Aliased as validate.
#
# If the argument is +false+ (default is +nil+), the context is set to <tt>:create</tt> if
# <tt>new_record?</tt> is +true+, and to <tt>:update</tt> if it is not.
#
# Validations with no <tt>:on</tt> option will run no matter the context. Validations with
# some <tt>:on</tt> option will only run in the specified context.
=> nil
बहुत बढ़िया, है ना? आपका डॉक्यूमेंटेशन कंसोल में ही है!
इंट्रोस्पेक्शन कमाल का है
मेरे कुछ पसंदीदा रूबी क्लासेस वे हैं जो आपको अपने कोड को अपने कोड के अंदर से इंस्पेक्ट करने देते हैं। Class, Module, और Method जैसी क्लासेस। इनके साथ, आप अपने कोड के बारे में बहुत कुछ सीख सकते हैं जैसे यह चलता है, और इसे मौके पर संशोधित कर सकते हैं। इन क्लासेस को अच्छी तरह से सीखें, उनके API का अध्ययन करें, और आप रूबी के साथ अद्भुत चीजें कर पाएंगे।