2012-08-29 13 views
18

मुझे दिलचस्पी है कि रेल कैसे before_filter जैसे फ़िल्टर लागू करते हैं।रेल_फिल्टर से पहले कैसे लागू होते हैं?

लेकिन स्रोत कोड पढ़ने के बाद, मैं अभी भी उलझन में हूं।

मैंने देखा कि रेल के ढांचे में filter_chain बनाए रखा गया है, और लक्ष्य विधि से पहले फ़िल्टर चलाएं।

लेकिन, मुझे एक महत्वपूर्ण प्रक्रिया नहीं समझती है: रेल कैसे एक विधि कॉलिंग कैप्चर करते हैं?

मेरा मतलब है, उदाहरण के लिए, मेरे पास कक्षा Dog है, और विधि छाल में before_filter सेट करें।

जब मैं dog.bark पर कॉल करता हूं, रेल को इस कॉलिंग को किसी भी तरह से कैप्चर करना चाहिए, और इसके बजाय इसकी संशोधित विधि को चलाएं।

हालांकि, मुझे स्रोत कोड में ऐसा कोड नहीं मिला है।

क्या कोई मुझे इस विचार को बता सकता है या बता सकता है कि कोड कहां स्थित है?

उत्तर

20

आप एक before_filter सेट करें, या किसी भी इसी तरह फिल्टर (लगता है after_filter, around_filter), तो आप ऐसा या तो एक Symbol या एक Proc, लैम्ब्डा या ब्लॉक के साथ कर रहे हैं जब।

before_filter :bark 
before_filter Proc.new { |k| k.bark } 

से ऊपर, एक ढेर here के प्रतीकों या ब्लॉक संलग्न कर देता है set_callback फोन करके। यह उस 'श्रृंखला' का निर्माण करता है जिसका आप उल्लेख कर रहे हैं।

इस 'श्रृंखला' में प्रत्येक आइटम ActiveSupport::Callbacks::Callback वर्ग का एक उदाहरण है। इस वर्ग

  • विधि (प्रतीक) जानता है या ब्लॉक यह (यानी। अपने वर्ग ':bark विधि)
  • संदर्भ में जो यह भीतर चलाना चाहिए (यानी। अपने Dog वर्ग) चलाना चाहिए

Callback उदाहरणों __update_callbacks में एक ActiveSupport::Callbacks::CallbackChain के साथ जोड़ दिया जाता है।

जब प्रत्येक Callback वर्ग आरंभ नहीं हो जाता, _compile_filter एक आम, प्रतिदेय प्रारूप में Symbol, Proc, लैम्ब्डा से फिल्टर को सामान्य, या ब्लॉक करने के लिए चलाया जाता है।

अंत में, जब CallbackChain चलाया जाता है, यह प्रत्येक Callback उदाहरण पर start, और अपने इस बिंदु कि फिल्टर वास्तव में उचित संदर्भ में निष्पादित किया जाता है पर कॉल करेगा।


यह कहना है कि आप नहीं तरह

before_filter dog.bark 

इस dog.bark निष्पादित और यह before_filter को वापसी मान CallbackChain संलग्न किया करने के लिए पारित करने के लिए जा रहा है एक फ़िल्टर बनाना होगा महत्वपूर्ण है। रेलवे के लिए बाद में निष्पादित करने के लिए before_filter पर कुछ प्रकार के निर्देशों को पास करना है। इसके बजाय आप

before_filter Proc.new { d = Dog.new; d.bark } 

Proc के भीतर कोड निष्पादित नहीं किया जाएगा। जब ऊपर की रेखा रेल द्वारा संचालित होती है। इसके बजाय, Proc को CallbackChain पर पास करने के लिए रेल कहा जा रहा है। Proc वह उचित है जिसे आप उचित समय पर निष्पादित करने के लिए रेल पर जा रहे हैं।


कैसे पहली जगह रेल पता है मैं कहा जाता है में: छाल

इस के लिए के रूप में, मान लें कि आपका Dog वर्ग बस

class Dog 
    def bark 

    end 

    def eat 

    end 
end 

के रूप में परिभाषित किया गया है (चलो हालांकि यह एक भयानक उदाहरण है), हो सकता है कि आप

जैसे कुछ चाहें
before_bark :eat 

इसके लिए आवश्यक है कि आप bark कॉलबैक परिभाषित करते हैं, और उसके बाद संबंधित bark कॉलबैक चलाने के लिए अपने bark विधि बताओ।

class Dog 
    extend ActiveModel::Callbacks 

    define_callbacks :bark 

    before_bark :eat 

    def bark 
    run_callbacks(:bark) { YOUR BARK CODE HERE } 
    end 

    def eat 

    end 
end 

आप देख सकते हैं कि ActiveRecord::Callbacks करता है।

यह वास्तव में एक बुरा उदाहरण है क्योंकि आप eat को bark से सीधे कॉल कर सकते हैं, लेकिन इसे बिंदु प्राप्त करना चाहिए।

+0

पहले आपको धन्यवाद! लेकिन अभी भी भ्रम। आपने कहा 'अंत में, जब कॉलबैकChain चलाया जाता है ...', और मेरा सवाल यह है कि रेलवे को कैलकबैक को कैसे पता चलाना चाहिए? कहें, अगर मैंने पहले_फिल्टर सेट किया है: कक्षा कुत्ते को खाएं। तब जब मैं कुत्ते को बुलाता हूं। बार्क,: पहले खाना चलाना चाहिए। लेकिन, रेल में पहली जगह कैसे पता है कि मैंने कहा है: छाल? – HanXu

+0

मैंने अपना जवाब अपडेट किया। – deefour

+0

बहुत स्पष्ट, लेकिन अभी भी थोड़ा उलझन में है। आपके उदाहरण में, हम छाल को मैन्युअल रूप से फिर से परिभाषित करते हैं, लेकिन रेल कुछ कोड द्वारा स्वचालित रूप से करता है। मुझे नहीं पता कि ये कोड कहां झूठ बोलते हैं। @ हेराल्ड के अनुसार, रेल ने प्रत्येक कार्रवाई को पहले से ही संशोधित किया है। मैंने सार कंट्रोलर :: बेस में 'attr_internal' देखा, क्या जादू होता है? – HanXu

1

रेल आपके द्वारा वर्णित तरीके से कॉल कैप्चर नहीं करता है। यदि आप AbstractController::Base.process देखते हैं तो यह प्रेषित कार्रवाई के लिए कॉल करने की विधि को देखेगा, फ़िल्टर चलाएं और फिर वास्तविक विधि को कॉल करें। दूसरे शब्दों में, आपकी नियंत्रक विधि को सीधे नहीं कहा जाता है, लेकिन इस process विधि के माध्यम से।

+0

मुझे यह मिला, रेल प्रत्येक विधि को नए आंतरिक नाम में बदलने के लिए 'attr_internal' का उपयोग करते हैं और नए नाम के साथ सभी चीजें करते हैं? – HanXu

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