2013-02-17 32 views
5

क्लास_वेल ब्लॉक के अंदर कक्षा चर को कैसे परिभाषित करता है? मैं निम्नलिखित है:मॉड्यूल # के अंदर class_eval के अंदर वर्ग चर परिभाषित करना

module Persist 
    def self.included(base) 
     # base is the class including this module 
     base.class_eval do 
      # class context begin 
      @@collection = Connection.new.db('nameofdb').collection(self.to_s.downcase) 
      def self.get id # Class method 
       #... 
      end 
     end 
    end 
    # Instance methods follow 
    def find 
     @@collection.find().first 
     #... 
    end 
end 

class User 
    include Persist 
end 

class Post 
    include Persist 
end 

कक्षाएं उपयोगकर्ता और पोस्ट दोनों :get दिखाने जब User.methods या Post.methods का उपयोग कर आत्मनिरीक्षण। जो समझ में आता है, क्योंकि उन्हें class_eval के संदर्भ में परिभाषित किया गया है और मुझे वही चाहिए जो मुझे चाहिए। इसी प्रकार विधि :find व्यक्तिगत कक्षाओं के example_method के रूप में दिखाया गया है।

हालांकि, मैंने जो क्लास वैरिएबल i.e. @@collection देखा था, मॉड्यूल स्तर class_variable बन गया है। जब मैं User.class_variables या Post.class_variables आत्मनिरीक्षण करता हूं, तो वे खाली हो जाते हैं। हालांकि Persist.class_variables:@@collection दिखाता है।

यह कैसे संभव है? कक्षा के class_eval ब्लॉक के अंदर संदर्भ नहीं है। तो परिवर्तनीय @@collection कक्षा पर परिभाषित नहीं होना चाहिए, न कि मॉड्यूल?

इसके अलावा, @@collection का मान हमेशा अंतिम श्रेणी का नाम है जिसमें इसे शामिल किया गया है। तो इस मामले में यह हमेशा 'पोस्ट' होता है और कभी भी 'उपयोगकर्ता' नहीं होता है। मुझे लगता है कि ऐसा इसलिए है क्योंकि यह एक मॉड्यूल स्तर चर है, यह हर शामिल पर बदल जाएगा। क्या ये सही है?

अंत में मैं इस संदर्भ में कक्षा चर परिभाषित कैसे करूं ताकि प्रत्येक वर्ग की अपनी @@collection परिभाषा हो।

उत्तर

5

कक्षा चर के लिए एक्सेसर विधियों को बनाने का एक तरीका होगा।

module Persist 
    def self.included(base) 
     # Adds class methods from 'ClassMethods' to including class. 
     base.extend(ClassMethods) 
     base.class_eval do 
      self.collection = Connection.new.db('nameofdb').collection(self.to_s.downcase) 
      # ... 
     end 
    end 
    module ClassMethods 
     def collection=(value) 
      @@collection = value 
     end 
     def collection 
      @@collection 
     end 
    end 
    # Instance methods follow 
    def find 
     self.class.collection.find().first 
     #... 
    end 
end 

class User 
    include Persist 
end 

class Post 
    include Persist 
end 

एक अन्य विधि मैं अपने प्रश्न का उत्तर देने चाकू ले लेंगे सहित वर्ग के वर्ग चर मॉड्यूल में accessors के माध्यम से class_variable_set, आदि

def self.included(base) 
    base.class_eval do 
     class_variable_set('@@collection', Connection.new.db('nameofdb').collection(self.to_s.downcase)) 
     # … 
    end 
end 

तक पहुँचने के लिए होगा " यह कैसे संभव है? कक्षा के वर्ग_वॉल ब्लॉक के अंदर संदर्भ नहीं है। "

class_eval विधि स्वयं बनाने के वर्ग में यह दिया ब्लॉक के अंदर पर लागू किया जा रहा है का उल्लेख करता है। यह आपको क्लास विधियों इत्यादि का आह्वान करने की इजाजत देता है। हालांकि, क्लास वेरिएबल का मूल्यांकन इस संदर्भ में किया जाएगा कि ब्लॉक - यहां मॉड्यूल से जुड़ा हुआ है।

उदाहरण के लिए, ऐसा करने का प्रयास करें:

class Foo 
    @@bar = 1 
end 

Foo.class_eval { puts @@bar } 

यह अपवाद ": ऑब्जेक्ट में अप्रारंभीकृत वर्ग चर @@ बार NameError" में परिणाम होगा। यहां दिया गया ब्लॉक "ऑब्जेक्ट", शीर्ष-स्तरीय नामस्थान के संदर्भ से जुड़ा हुआ है।

+0

धन्यवाद! एक बहुत स्पष्ट स्पष्टीकरण। मैं class_variable_set का उपयोग कर समाप्त हुआ। Class12ethods का उपयोग कर –

+1

मॉड्यूल से संबंधित स्थैतिक चर भी बनाता है ... – Geoffroy

+0

इस उत्तर को ठीक करने की आवश्यकता है। ClassMethods मॉड्यूल का उपयोग करके प्रस्तुत की गई विधि प्रश्न की समस्या को ठीक करने के लिए काम नहीं करती है। क्लास वेरिएबल्स घोषित किए गए हैं जो मॉड्यूल को भी स्कॉप्ड किए गए हैं और इस प्रकार कक्षाओं सहित सभी में साझा किया जाता है। 'Class_variable_set' विधि काम करती है, और इस उत्तर में एकमात्र जानकारी होनी चाहिए –