I have a mixin for which I would like to get a list of all the classes that have included it. In the mixin module, I did the following:
module MyModule def self.included(base) @classes ||= [] @classes << base.name end def self.classes @classes end end class MyClass include MyModule end
This works pretty well:
> MyModule.classes #=> nil > MyClass.new #=> #<MyClass ...> > MyModule.classes #=> ["MyClass"]
Now, I would like to extract this part out into a separate module that can be included in my other mixins. So, I came up with the following:
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
This doesn't work though, because the #included(module_base) method being added to MyModule from ListIncludedClasses is never getting run. Interestingly enough, it does successfully add #classes to MyModule.
> MyModule.classes #=> "...adding Rateable to ListIncludedClasses.classes" => nil > ListIncludedClasses #=> ["MyModule"] > MyClass.new #=> #<MyClass ...> # ^^ THIS SHOULD BE ADDING MyClass TO MyModule.classes ^^ > MyModule.classes #=> nil
What am I missing?
Classes are object-oriented, but modules are not. So only classes can be instantiated as objects.
To get the class name of an instance in Python: Use the type() function and __name__ to get the type or class of the Object/Instance. Using the combination of the __class__ and __name__ to get the type or class of the Object/Instance.
Modules allow instructors to organize content to help control the flow of the course. Modules are used to organize course content by weeks, units, or a different organizational structure.
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]
Actually, your module extension module works. The problem is in your test: when you created a random unnamed class with Class.new
, you forgot to include MyModule
. As a side note, you can take your read-only accessor for classes that include the module and use the helpful Module#attr_reader
method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With