2012-05-06 18 views
19

तक पहुंच के साथ रेल सहायकों को ओवरराइड करें, मैं रेल के परिचित सहायकों का उपयोग करना चाहता हूं, लेकिन थोड़ा बदलकर कार्यक्षमता के साथ। जिस तरह से मैं इसे देख, मैं की तरह कुछ करने के लिए सक्षम होना चाहते हैं:मूल

  1. बंदर पैचिंग: रेल सहायक मॉड्यूल को पुन: खोलने

    module AwesomeHelper 
        #... create alias of stylesheet_link_tag to old_stylesheet_link_tag 
        def stylesheet_link_tag(*args) 
        if @be_awesome 
         awesome_stylesheet_link_tag *args 
        else 
         old_stylesheet_link_tag *args 
        end 
        end 
    end 
    

    तरह से मैं इसे देख, मैं तीन विकल्प हैं । यदि रेल टीम कभी भी अपने सहायक मॉड्यूल का नाम बदलती है, तो मेरा कोड बेकारता का स्रोत बन जाता है। दुर्बल नहीं, लेकिन आदर्श नहीं है।

  2. विभिन्न विधि नामों का उपयोग करें: आम रेल इंटरफेस से चिपकने की कोशिश करना मेरा पतन हो सकता है। मेरे परिवर्तन अन्य डेवलपर्स के लिए भ्रम का स्रोत बन सकते हैं
  3. अलग-अलग तरीकों (नया): यह सुनिश्चित नहीं है कि यह काम करेगा या नहीं, या यह 1 के समान ही कमजोर होगा। यह शोध करेगा, लेकिन यह अच्छा हो सकता है प्रस्थान बिंदू।

तो सवाल यह है कि, क्या मैं इन उप-इष्टतम समाधानों में से एक के साथ फंस गया हूं, या क्या कोई अन्य तरीका है जिसे मैंने नहीं माना है? यदि मैं विकल्प 3 के लिए जाता हूं, तो क्या रेलवे सहायक मॉड्यूल को सीधे संबोधित किए बिना ऐसा करने का कोई तरीका है?

(नोट:। मैं संदर्भ निकाल दिया है, के रूप में यह सवाल करने के लिए कुछ भी नहीं कहते हैं)

उत्तर

30

आपके किसी भी सूचीबद्ध विकल्पों की तुलना में बेहतर तरीका है। बस super का उपयोग करें:

module AwesomeHelper 
    def stylesheet_link_tag(*sources) 
    if @be_awesome 
     awesome_stylesheet_link_tag *sources 
    else 
     super 
    end 
    end 
end 

AwesomeHelper में stylesheet_link_tag ओवरराइड करना है कि यह सुनिश्चित करेंगे, जब stylesheet_link_tag लागू हो जाता है, रूबी यह विधि देखने राह में इससे पहले कि यह ActionView::Helpers::AssetTagHelper हिट का सामना करेंगे। यदि @be_awesometrue है, तो आप वहां शुल्क लेते हैं और वहां चीजों को रोकते हैं, और यदि नहीं, तो super पर कॉल किए बिना कॉल पारदर्शी रूप से रेल कार्यान्वयन तक सभी तर्कों से गुज़रेंगे। इस तरह आपको रेल कोर कोर टीम के बारे में चिंता करने की ज़रूरत नहीं है!

+0

आप जानते हैं कि ... यह इतना पागल स्पष्ट है, मैं अपने दिमाग को काम करने के लिए रैक करने की कोशिश कर रहा हूं क्यों मैंने सोचा कि यह काम नहीं करेगा! मैं आज रात कोशिश कर रहा हूं और, अगर यह काम करता है, तो मेरे दिमाग में गंभीर शब्द होंगे, शायद एक ईंट की दीवार शामिल है। बेशक, अपने उत्तर को स्वीकार करने के बाद ...: डी – user208769

+1

@ user208769 Hehehe। वह तो कमाल है। जैसा कि मैं सबसे अच्छा समझता हूं, इस तरह से ओवरराइडिंग विधियों को आम तौर पर किसी भी परिस्थिति में बेहतर माना जाता है। [कक्षा # पूर्वजों] (http://ruby-doc.org/core-1.9.3/Module.html#method-i-ancestors) हाइजैक विधि के लिए विधि लुकअप पथ में एक अच्छी जगह लगाने में वास्तव में सहायक हो सकता है प्रेषण (या ओवरराइड के साथ आपका कस्टम मॉड्यूल सबसे अच्छा प्रभाव में शामिल करने की आवश्यकता है)। – Cade

+0

क्या? :) आप मज़ाक कर रहे हैं! यह एक बड़ा गेटचा है! आपके रास्ते में आपको प्रत्येक कक्षा में सहायक शामिल करना होगा जिसमें एसेटटैगहेपर शामिल है। समय उड़ता है और आप या कोई और आपके पैच को शामिल करने की आवश्यकता के बारे में भूल सकता है। आप बस एसेटटैगहेपर शामिल करते हैं और आश्चर्यचकित होना शुरू करते हैं: मेरी साइट अब अलग दिखती क्यों है? यह अच्छा है जब आप और पैच निर्माता एक ही व्यक्ति हैं। लेकिन अगर नहीं तो क्या? – jdoe

6

मैं इस मणि का उपयोग नहीं करते, तो मैं एक और अधिक सामान्य तरीके से आप जवाब देंगे।

मान लें कि आप link_to सहायक (हाँ, प्रदूषित उदाहरण, लेकिन विचार दिखाते हैं) पर कॉल लॉग करना चाहते हैं। एपीआई में देखकर आपको ActionView::Helpers::UrlHelper मॉड्यूल के अंदर स्थित link_to समझने में मदद मिलती है। तो, आप अपने, कहते हैं, config/initializers निम्नलिखित सामग्री के साथ निर्देशिका में कुछ फ़ाइल बनाने:

# like in config/initializers/link_to_log.rb 
module ActionView::Helpers::UrlHelper 

    def link_to_with_log(*args, &block) 
     logger.info '**** LINK_TO CALL ***' 
     link_to_without_log(*args, &block) # calling the original helper 
    end 

    alias_method_chain :link_to, :log 
end 

इस कार्यक्षमता का मूल - alias_method_chain (क्लिक करने योग्य)। विधि xxx_with_feature को परिभाषित करने के बाद इसका उपयोग करें।

+0

हाँ, इस दृष्टिकोण है कि मैं क्या द्वारा "बंदर पैचिंग विशिष्ट रेल मॉड्यूल" का मतलब था - जो अच्छी तरह से काम करता है, लेकिन अगर रेल कोर उनके मॉड्यूल के नाम, मेरी कोड टूट जाता है बदल जाते हैं। यह एक बड़ा सौदा नहीं हो सकता है, लेकिन मैं यह देखने के लिए उत्सुक हूं कि अन्य समाधान हैं या नहीं। उस ने कहा, alias_method_chain के बारे में भूल गया था, मुझे याद दिलाने के लिए धन्यवाद! – user208769

+0

पीएस: मणि उदाहरण को हटाने के लिए प्रश्न को अद्यतन किया है। उम्मीद है कि यह लेआउट कम भ्रमित है! धन्यवाद। – user208769

+0

जोखिम हमेशा रहता है! यदि आप 'alias_method_chain' के बारे में चिंता करते हैं तो आपको यह नहीं करना चाहिए: यह संस्करण 1.4.0 (वर्ष 2007) के बाद से मौजूद है। यदि आप अपने कार्यक्रम के अन्य हिस्सों के बारे में चिंता करते हैं तो सभ्य परीक्षण कवरेज सुनिश्चित करें। – jdoe

2

मैं आपको वास्तव में कॉलर के लिए स्पष्ट तरीके से रेल तरीकों के व्यवहार को ओवरराइड करने के लिए अपने विकल्प # 2 पर विचार करने के लिए प्रोत्साहित करता हूं।

आपकी नई विधि को awesome_stylesheet_link_tag कहा जाना चाहिए ताकि अन्य रेल देव आपके कोड पढ़ सकें और सवाल पूछ सकें "लिंक टैग के बारे में इतना बढ़िया क्या है?"।

एक छोटे से परिवर्तन के रूप में आप ओवरराइड कर सकते हैं लेकिन :awesome => true में एक तर्क के रूप में पास करते हैं ताकि कम से कम एक सुराग हो कि कुछ चल रहा है।

stylesheet_link_tag जैसे व्यापक रूप से उपयोग की जाने वाली विधि के व्यवहार को बदलने से संभावित भविष्य की गलतफहमी पैदा होती है जहां किसी की आवश्यकता नहीं होती है।

+0

धन्यवाद। आम तौर पर मैं सहमत हूं, इस विशेष मामले में मुझे लगता है कि स्थिरता उचित है - मैं इसे bad_pdf का उपयोग करने के लिए कर रहा हूं और वास्तव में एक ही कोड पीडीएफ या वेब पेज उत्पन्न करता है। जबकि डिफ़ॉल्ट रूप से evil_pdf करता है जैसा कि आप कहते हैं (evil_pdf_stylesheet_link_tag), इसके लिए मुझे बहुत अधिक दोहराव की आवश्यकता है, और मुझे लगता है कि यह उम्मीद करना स्वीकार्य है कि यदि आप पीडीएफ उत्पन्न कर रहे हैं तो कार्यक्षमता बदल सकती है। लेकिन आप एक अच्छा मुद्दा बनाते हैं, और कुछ आसान टिप्स, तो धन्यवाद। – user208769

4

alias_method उपयोग करके देखें:

module AwesomeHelper 
    alias_method :original_stylesheet_link_tag, :stylesheet_link_tag 

    def stylesheet_link_tag(*sources) 
    if @be_awesome 
     awesome_stylesheet_link_tag *sources 
    else 
     original_stylesheet_link_tag *sources 
    end 
    end 
end 
संबंधित मुद्दे