2012-03-01 13 views
5

मुझे आपके लिए यह देखने दें।ActiveRecord श्रृंखला में अंतिम विधि कॉल का पता कैसे लगाता है?

class Product < ActiveRecord::Base 
end 

Product.first.title 
#=> "My sample product" 

यहां कुछ असाधारण नहीं है। बस एक साधारण विधि कॉल। अब निम्नलिखित उदाहरण पर एक नज़र डालें।

class Product < ActiveRecord::Base 
    def method_missing 
    end 
end 

Product.first.title 
#=> nil 

Product.first 
Product.first.title 
#=> "My sample product" 

यह कैसे संभव है? किसी भी तरह से वे विधि श्रृंखला का अंत निर्धारित करते हैं और उस पर कार्य करते हैं? कम से कम मेरा सिद्धांत है।

क्या कोई इस व्यवहार को समझा सकता है?

उत्तर

7

आप चीजों की जांच के लिए irb का उपयोग करने का एक आर्टिफैक्ट देख रहे हैं।

जब आप कहते हैं कि यह:

> Product.first.title 
#=> nil 

आपका method_missing को बुलाया जाएगा आलसी लोड title विधि और आप nil मिलता है।

जब आप कहते हैं कि यह:

> Product.first 

आप प्रभावी रूप से इस कार्य कर रहे हैं:

> p = Product.first; puts p.inspect 

पहले उत्पाद उदाहरण लोड किया जाएगा और उसके बाद irb उस पर inspect कॉल करेंगे और एआर जोड़ देगा रास्ते में accessor विधियों। नतीजा यह है कि उत्पाद में अब title विधि होगी। इसलिए, यह कर:

> Product.first 
> Product.first.title 

पर अपने सभी method_missing फोन नहीं होगा के रूप में वहाँ Product.first.title कॉल करने के लिए के लिए एक असली title विधि हो जाएगा।

आप इस तरह फिर से प्रयास करें:

> Product.first; nil 
> Product.first.title 

आप दो nil रों देखेंगे।


जहाँ तक श्रृंखलन चला जाता है के रूप में, ActiveRecord वास्तव में अंत का पता लगाने नहीं है कि यह सिर्फ इतना है कि कुछ विधि स्वाभाविक रूप से कहता है डेटाबेस से वास्तविक डेटा की आवश्यकता होती है और कुछ नहीं है।

आप कॉल where, order, या अन्य क्वेरी करने से किसी भी विधि, आप एक ActiveRecord::Relation उदाहरण वापस पाने और यदि आप श्रृंखला अधिक है कि संबंध वस्तु पर क्वेरी के तरीकों और स्कोप कर सकते हैं। उदाहरण के लिए, where (जो ActiveRecord :: रिलेशन ActiveRecord::QueryMethods शामिल करके हो जाता है) इस तरह दिखता है:

def where(opts, *rest) 
    return self if opts.blank? 

    relation = clone 
    relation.where_values += build_where(opts, rest) 
    relation 
end 

तो यह सिर्फ वर्तमान क्वेरी की एक प्रतिलिपि बनाता, प्रतिलिपि के लिए कुछ चीजें कहते हैं, और आप प्रतिलिपि देता है वापस।

यदि आप फोन first, last, to_a, all, Enumerable से किसी भी विधि (अर्थात आप each कहते हैं), ...तो आप विशिष्ट उदाहरणों के बारे में पूछ रहे हैं और ActiveRecord को प्रश्न में मॉडल उदाहरण (ओं) को समझने के लिए क्वेरी निष्पादित करनी होगी। उदाहरण के लिए, ActiveRecord::Relation#to_a इस तरह दिखता है:

def to_a 
    logging_query_plan do 
    exec_queries 
    end 
end 

और all एक आवरण के आसपास to_a से थोड़ा अधिक है।

ActiveRecord वास्तव में नहीं जानता कि श्रृंखला का अंत कहां है, यह डेटाबेस से कुछ भी लोड नहीं करता है जब तक कि आपको यह न कहें कि श्रृंखला कहां समाप्त होती है आगे बढ़कर मुझे कुछ डेटा पुनर्प्राप्त करें

+0

मुझे लगता है कि यह श्रृंखला के अंत का पता लगाता है: यह वह जगह है जहां आप एक खोजक प्रॉक्सी ऑब्जेक्ट वापस नहीं लेते हैं! – phoet

+0

यह सवाल नहीं है कि सवाल क्या है। सवाल यह है कि क्यों '' 'Product.first.title''' रिटर्न' '' nil''' जब तक '' 'Product.first''' कहा जाता है, जब' '' method_missing''' एक मॉडल के अंदर किया जाता है। एक बार जब आप '' 'product.first'' शीर्षक कहलाते हैं तो' 'मेरा नमूना ब्लॉग '' '' लौटाता है। – user544941

+0

@ user544941: क्या जगह या उसके 'method_missing' को दरकिनार कर रहा है: आह, मैं वह क्या बारे में पूछ देखें। –