Ruby Language
शोधन
खोज…
टिप्पणियों
शोधन कार्यक्षेत्र हैं, जिसका अर्थ है कि वे उस समय से प्रभावी हैं जब तक कि वे पाली को नियंत्रित नहीं using
(कीवर्ड का using
)। आमतौर पर नियंत्रण एक मॉड्यूल, वर्ग, या फ़ाइल के अंत तक बदल दिया जाता है।
सीमित दायरे के साथ बंदर पैचिंग
मंकी पैचिंग का मुख्य मुद्दा यह है कि यह वैश्विक दायरे को प्रदूषित करता है। आपका कोड काम करना उन सभी मॉड्यूल की दया पर है जिनका उपयोग आप एक दूसरे के पैर की उंगलियों पर नहीं करते हैं। इसके लिए रूबी समाधान परिशोधन है, जो मूल रूप से सीमित दायरे में बंदर पैच हैं।
module Patches
refine Fixnum do
def plus_one
self + 1
end
def plus(num)
self + num
end
def concat_one
self.to_s + '1'
end
end
end
class RefinementTest
# has access to our patches
using Patches
def initialize
puts 1.plus_one
puts 3.concat_one
end
end
# Main scope doesn't have changes
1.plus_one
# => undefined method `plus_one' for 1:Fixnum (NoMethodError)
RefinementTest.new
# => 2
# => '31'
दोहरे उद्देश्य वाले मॉड्यूल (शोधन या वैश्विक पैच)
रिफाइनमेंट्स का उपयोग करके पैच को स्कोप करना एक अच्छा अभ्यास है, लेकिन कभी-कभी इसे विश्व स्तर पर लोड करना अच्छा होता है (उदाहरण के लिए विकास, या परीक्षण)।
उदाहरण के लिए कहें कि आप एक कंसोल शुरू करना चाहते हैं, आपके पुस्तकालय की आवश्यकता है, और फिर वैश्विक स्कोप में पैच किए गए तरीके उपलब्ध हैं। आप इसे परिशोधन के साथ नहीं कर सकते क्योंकि using
करने की आवश्यकता को वर्ग / मॉड्यूल परिभाषा में कहा जाता है। लेकिन कोड को इस तरह से लिखना संभव है कि यह दोहरे उद्देश्य से हो:
module Patch
def patched?; true; end
refine String do
include Patch
end
end
# globally
String.include Patch
"".patched? # => true
# refinement
class LoadPatch
using Patch
"".patched? # => true
end
गतिशील शोधन
शोधन की विशेष सीमाएँ हैं।
refine
केवल एक मॉड्यूल दायरे में उपयोग किया जा सकता है, लेकिन send :refine
का उपयोग करके प्रोग्राम किया जा सकता है send :refine
।
using
करना अधिक सीमित है। इसे केवल कक्षा / मॉड्यूल परिभाषा में कहा जा सकता है। फिर भी, यह एक मॉड्यूल की ओर इशारा करते हुए एक चर को स्वीकार कर सकता है, और एक लूप में आमंत्रित किया जा सकता है।
इन अवधारणाओं को दिखाने वाला एक उदाहरण:
module Patch
def patched?; true; end
end
Patch.send(:refine, String) { include Patch }
patch_classes = [Patch]
class Patched
patch_classes.each { |klass| using klass }
"".patched? # => true
end
चूंकि using
इतना स्थिर है, इसलिए लोड ऑर्डर के साथ जारी किया जा सकता है यदि शोधन फ़ाइलें पहले लोड नहीं की जाती हैं। इसका पता लगाने का एक तरीका यह है कि पैचेड क्लास / मॉड्यूल की परिभाषा को एक प्रॉप में लपेटा जाए। उदाहरण के लिए:
module Patch
refine String do
def patched; true; end
end
end
class Foo
end
# This is a proc since methods can't contain class definitions
create_patched_class = Proc.new do
Foo.class_exec do
class Bar
using Patch
def self.patched?; ''.patched == true; end
end
end
end
create_patched_class.call
Foo::Bar.patched? # => true
Proc को कॉल करने से पैच क्लास Foo::Bar
बनता है। सभी कोड लोड होने के बाद तक इसमें देरी हो सकती है।