2010-10-12 11 views
14

शामिल है मेरे पास एक मिश्रण है जिसके लिए मैं इसे शामिल करने वाले सभी वर्गों की एक सूची प्राप्त करना चाहता हूं।कक्षाओं की एक सूची प्राप्त करना जिसमें मॉड्यूल

module MyModule 
    def self.included(base) 
    @classes ||= [] 
    @classes << base.name 
    end 

    def self.classes 
    @classes 
    end 
end 

class MyClass 
    include MyModule 
end 

यह बहुत अच्छी तरह से काम करता है::

> MyModule.classes #=> nil 
> MyClass.new #=> #<MyClass ...> 
> MyModule.classes #=> ["MyClass"] 

अब, मैं एक अलग मॉड्यूल है कि मेरे अन्य में शामिल किया जा सकता में इस हिस्से बाहर निकालने के लिए चाहते हैं mixin मॉड्यूल में, मैं निम्नलिखित किया mixins। तो, मैं निम्नलिखित के साथ आया था:

module ListIncludedClasses 
    def self.included(base) 
    p "...adding #{base.name} to #{self.name}.classes" 

    @classes ||= [] 
    @classes << base.name 

    base.extend(ClassMethods) 
    end 

    def self.classes 
    @classes 
    end 

    module ClassMethods 
    def included(module_base) 
     p "...adding #{module_base.name} to #{self.name}.classes" 

     @module_classes ||= [] 
     @module_classes << module_base.name 
     super(module_base) 
    end 
    def classes 
     @module_classes 
    end 
    end 

end 

module MyModule 
    include ListIncludedClasses 
end 

यह, हालांकि काम नहीं करता क्योंकि #included (module_base) विधि ListIncludedClasses से MyModule में जोड़ा जा रहा कभी नहीं रन हो रही है। दिलचस्प है, यह सफलतापूर्वक MyClodule में #classes जोड़ता है।

> MyModule.classes #=> 
    "...adding Rateable to ListIncludedClasses.classes" 
    => nil 
> ListIncludedClasses #=> ["MyModule"] 
> MyClass.new #=> #<MyClass ...> 
# ^^ THIS SHOULD BE ADDING MyClass TO MyModule.classes ^^ 
> MyModule.classes #=> nil 

मुझे क्या याद आ रही है?

+0

यह इंगित करना न भूलें कि मैंने आपके प्रश्न का उत्तर दिया है! – Tom

+0

क्या आपने यह कोशिश की है: http://stackoverflow.com/questions/3527445/when-are-modules-cluded-in-a-ruby-class-running-in-rails – rickypai

उत्तर

14
module MyMod; end 

class A; include MyMod; end 
class B < A; end 
class C; end 

ObjectSpace.each_object(Class).select { |c| c.included_modules.include? MyMod } 
    #=> [B, A] 
1

आपको पूर्व में वर्ग स्तर के तरीकों को जोड़ने के बजाय विस्तार के बजाय विस्तार का उपयोग करना चाहिए, जबकि बाद के - उदाहरण स्तर विधियां (आपके पास @classes तक पहुंच क्यों है)।

इस प्रयास करें:

module MyModule 
    extend ListIncludedClasses::ClassMethods 
end 
+2

मुझे नहीं पता कि आपने इसे याद किया है या नहीं, लेकिन विस्तार (ClassMethods) self.included (आधार) विधि में है, इसलिए यह कक्षा विधियों का विस्तार कर रहा है। अन्य उदाहरण विधियां हैं जिन्हें जोड़ने की आवश्यकता है; यह उदाहरण विधियों और वर्ग विधियों को विस्तारित करने दोनों के लिए लोकप्रिय रूप से स्वीकार्य तकनीक है। साथ ही, क्लास विधियों को सीधे विस्तारित करते हुए, जैसा कि आपने सुझाव दिया है, कोई फर्क नहीं पड़ता। – jangosteve

2

वास्तव में, अपने मॉड्यूल विस्तार मॉड्यूल काम करता है। समस्या आपके परीक्षण में है: जब आपने Class.new के साथ यादृच्छिक अनामित वर्ग बनाया, तो आप MyModule शामिल करना भूल गए। एक साइड नोट के रूप में, आप कक्षाओं के लिए केवल पढ़ने के लिए एक्सेसर ले सकते हैं जिसमें मॉड्यूल शामिल है और उपयोगी Module#attr_reader विधि का उपयोग करें।

+0

उत्तर के लिए धन्यवाद। हां, यह तब काम करता है जब मैं इसे आजमाता हूं, मुझे यकीन नहीं है कि मैं उस वक्त क्या कर रहा था। मुझे लगता है कि मेरे पास इसे अलग करने के बजाय रेल परियोजना में था, तो कौन जानता है। ऐसा नहीं था कि मैं 'MyClass 'परिभाषा को' शामिल 'के साथ भूल गया था, मैंने अभी उपर्युक्त उदाहरण में इसे फिर से टाइप नहीं किया है। अन्यथा, MyClass.new 'uninitialized निरंतर MyClass' फेंक दिया होगा। इसके अलावा 'मॉड्यूल # attr_reader' उदाहरण विधियों को बनाता है, इसलिए हाँ, मैं इसे' ClassMethods' के अंदर और फिर 'ListIncludedClasses' में' वर्ग << स्वयं' ब्लॉक के अंदर भी इस्तेमाल कर सकता था। यह अधिक कुशल है, इसलिए उत्पादन में जाने का रास्ता होगा। – jangosteve

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