2015-06-04 7 views
6

मैं विधि एकल मॉडल श्रेणी के उदाहरण पर व्यवहार को ओवरराइड करना चाहता हूं। चर को मानते हुए @alert कहा जाता है इसके बारे में जाने का सबसे अच्छा तरीका क्या है? स्पष्ट होने के लिए, मैं पूरी कक्षा के लिए इस विधि के व्यवहार को संशोधित करना चाहता हूं।एकल ऑब्जेक्ट पर बंदर पैच विधि


अस्वीकरण:

मैं यह करने के false वापस जाने के लिए जब मैं यह इतना है कि मैं निम्नलिखित कोड से निपटने त्रुटि के लिए इकाई परीक्षण लिख सकते हैं करना चाहते हैं विधि के लिए मजबूर करने की जरूरत है। मैं समझता हूं कि यह सबसे अच्छा अभ्यास नहीं हो सकता है।

+1

के बारे में मैं शब्द "बंदर पैच" के आपके उपयोग को सही करने के था - यह केवल रूबी के अंतर्निहित तरीकों में से संशोधन के लिए आवेदन किया सोच - लेकिन googling के बाद ऐसा लगता है इसके अर्थ के रूप में कोई आम सहमति नहीं है। उदाहरण के लिए, [यह SO सवाल] देखें (http://stackoverflow.com/questions/394144/what-does-monkey-patching-exactly-mean-in-ruby)। –

+0

@CarySwoveland ऐतिहासिक रूप से "पैस पैच" का अर्थ है मौजूदा विधियों को अपने स्वयं के कार्यान्वयन के साथ रोकना जहां ये पूरी तरह से लेते हैं। इस मामले में यह एक "नकली" ऑपरेशन है, जहां यह केवल एक वस्तु को बदल रहा है, और अन्य वस्तुओं, दोनों मौजूदा और भविष्य में बनाए गए, अप्रभावित हैं। – tadman

+0

यह एक विधि स्टब की तरह बहुत गंध करता है, जो किसी भी सभ्य परीक्षण ढांचे को समायोजित करेगा। – zetetic

उत्तर

7

बस वस्तु पर एक विधि को परिभाषित:

class Thing 
    def greeting 
    'yo, man' 
    end 
end 

Thing.instance_methods(false) 
    #=> [:greeting] 

object = Thing.new 
    #=> #<Thing:0x007fc4ba276c90> 

object.greeting 
    #=> "yo, man" 

object पर दो विधियों को परिभाषित करें (जो object की सिंगलटन कक्षा में उदाहरण विधियां होंगी।

def object.greeting 
    'hey, dude' 
end 

def object.farewell 
    'see ya' 
end 

object.methods(false) 
    #=> [:greeting, :farewell] 
object.singleton_class.instance_methods(false) #=> [:greeting, :farewell] 

object.greeting 
    #=> "hey, dude" 
object.farewell 
    #=> "see ya" 

new_obj = Thing.new 
new_obj.greeting 
    #=> "yo, man" 
new_obj.farewell 
    #NoMethodError: undefined method `farewell' for #<Thing:0x007fe5a406f590> 

निकालें object की सिंगलटन विधि greeting

object.singleton_class.send(:remove_method, :greeting) 

object.methods(false) 
    #=> [:farewell] 
object.greeting 
    #=> "yo, man" 

एक और object की सिंगलटन वर्ग से :greeting दूर करने के लिए जिस तरह से इस प्रकार है।

class << object 
    remove_method(:greeting) 
end 
+1

कभी-कभी यह मॉड्यूल बनाकर और व्यक्तिगत ऑब्जेक्ट में मिश्रण करके अधिक स्पष्ट रूप से किया जाता है। – tadman

+0

टाइपो: 'Thing.new hi'' Thing.new.hi' होना चाहिए। अपवाद तब होगा 'NoMethodError: अपरिभाषित विधि \' hi '# '' नाम त्रुटि के बजाय: ... ' – nitsas

+0

@nitsas, धन्यवाद। –

2

एक वस्तु बनाने के बाद, उस पर "define_method" कहते हैं:

किया कि
object = Thing.new 
object.define_method("update_attributes") { return false } 

, object.update_attributes अब लौटना चाहिए false

+0

ऑब्जेक्ट 'ActiveRecord :: Base' से प्राप्त होता है और मुझे उस पर 'define_method' कॉल करने का प्रयास करने वाला' NoMethodError' प्राप्त हो रहा है। कोई उपाय? यह स्पष्ट हो सकता है लेकिन मैं रूबी subtleties पर रूबी के लिए अपेक्षाकृत नया हूँ। – steve

+0

'define_method' केवल 'मॉड्यूल' पर परिभाषित किया गया है, लेकिन 'ऑब्जेक्ट' एक 'मॉड्यूल' नहीं है, यह 'थिंग' है। –

संबंधित मुद्दे