tags:

views:

98

answers:

4

I have a class that has a number of modules that are mixed in with it based on some runtime criteria.

I want to be able to get a list of what modules have been mixed into this class. How can you do that?

UPDATE

So when I said class I meant object as it is the object that is being extended at runtime using:

obj.extend(MyModule)

obj.included_modules and obj.ancestors don't exist so you can't get the modules that have been mixed in from there.

+6  A: 

Try:

MyClass.ancestors.select {|o| o.class == Module }

for example:

>> Array.ancestors.select {|o| o.class == Module}
=> [Enumerable, Kernel]

UPDATE

To get the modules mixed into an object instance at runtime you'll need to retrieve the eigenclass of the instance. There is no clean way to do this in Ruby, but a reasonably common idiom is the following:

(class << obj; self; end).included_modules

If you find yourself using this a lot, you can make it generally available:

module Kernel
  def eigenclass
    class << self
      self
    end
  end
end

and the solution is then:

obj.eigenclass.included_modules
Daniel Lucraft
thanks that does the trick!
Derek Ekins
There is a ready-made method for that, called `included_modules`.
Swanand
So there is. Thanks for the tip.
Daniel Lucraft
Turns out I jumped the gun. I have upated the question with some more details.
Derek Ekins
@Daniel: Good one. +1 from me.
Swanand
+5  A: 

This might be a better idea:

MyClass.included_modules
irb(main):001:0> Array.included_modules
=> [Enumerable, Kernel]
Swanand
+1  A: 

If you're looking for the whole list, Swanand's answer is your best bet.

If, on the other hand, you want to check whether a class includes a particular module, the < operator is your friend:

module Foo
end

class Bar
  include Foo
end

Bar < Foo
# => true
James A. Rosen
+1  A: 

Only classes can story methods and when you add a method to an instance you are actualy adding it to the objects metaclass. The module you are looking for will be in this metaclass ancestors list.

module TestModule; end

obj = "test"
obj.extend(TestModule)

class Object
  def metaclass
    class << self; self; end
  end
end

obj.metaclass.ancestors
# => [TestModule, String, Comparable, Object, Kernel, BasicObject]
David Billskog