How to get modules included by a class/module (not those fro

Is there a way to get only the modules included by a given class.
Using included_modules returns also the modules that are included by
the superclass(es).

Example :
class MyClass
end
MyClass.included_modules

will return Kernel

As a given module may be included several times in the class hierarchy
(e.g. by the class and by one of its superclass), just getting all
included modules and removing the included modules from the superclasses
may not be a solution. The given module may have been removed
erroneously.

It would have been great if included_modules takes a boolean parameter
in order to disable the recursion like instance_methods for example.

Thanks for any help.

Ruby A. schrieb:

Is there a way to get only the modules included by a given class.
Using included_modules returns also the modules that are included by
the superclass(es).
(…)
As a given module may be included several times in the class
hierarchy (e.g. by the class and by one of its superclass), just
getting all included modules and removing the included modules from
the superclasses may not be a solution. The given module may have
been removed erroneously.

Including a module in a class that already has been included by one of
its superclasses doesn’t change the inheritance hierarchy:

module M
end

class P
include M
end

class C < P
end

p C.ancestors # => [C, P, M, Object, Kernel]

class C
include M
end

p C.ancestors # => [C, P, M, Object, Kernel]

The only way to create the situation you describe above would be to
include the module in the child class before including it in the
superclass. If you want to detect this, you could try the following
code:

class Class
def my_own_included_modules
ancestors.inject([]) { |acc, mod|
break acc if mod == superclass
acc << mod unless mod == self
acc
}
end
end

p P.my_own_included_modules # => [M]
p C.my_own_included_modules # => []

class P2
end

class C2 < P2
include M
end

class P2
include M
end

p C2.ancestors # => [C2, M, P2, M, Object, Kernel]

p P2.my_own_included_modules # => [M]
p C2.my_own_included_modules # => [M]

Out of curiosity: why do you need this?

Regards,
Pit

Pit,

Including a module in a class that already has been included by one of
its superclasses doesn’t change the inheritance hierarchy:

module M
end

class P
include M
end

class C < P
end

p C.ancestors # => [C, P, M, Object, Kernel]

class C
include M
end

p C.ancestors # => [C, P, M, Object, Kernel]

The only way to create the situation you describe above would be to
include the module in the child class before including it in the
superclass.

You are absolutely right ! I did not catch this.
This seems to be a similar behaviour as for a class variable/method :

class B
@@var = “Hello”
end

class C < class B
end

The class variable @@var is shared/inherited in C. Similar as the case
where there is only one include.

Conversely :

class B
end

class C < class B
@@var = “Hello”
end

class B
@@var = “Goodbye”
end

The two class variables @@var are different. This is similar as the case
where there is an include at each class.

I know that this behaviour for class variable/method will change with
Ruby 2.0.
(A class variable/method will be static to the class)
Will it be the same for module inclusion ??

class Class
def my_own_included_modules
ancestors.inject([]) { |acc, mod|
break acc if mod == superclass
acc << mod unless mod == self
acc
}
end
end

This is exactly what I need.

Out of curiosity: why do you need this?

I just want to know/understand :

  • the hierarchy (inheritance) between the Ruby classes
  • which class really includes which module(s)

Thanks a lot.

Chauk-Mean.

class C < P
rick@frodo:~$ ruby1.8 modtest.rb
[C, P, M, Object, Kernel]
[C, P, M, Object, Kernel]
rick@frodo:~$ ruby1.9 modtest.rb
[C, P, M, Object, Kernel, BasicObject]
[C, M, P, M, Object, Kernel, BasicObject]

Thanks for your reply.
This is what I expected as this is consistent with the new class
var/methods behaviour.

I wrote about this back in October
http://talklikeaduck.denhaven2.com/articles/2006/10/09/a-subtle-change-to-mixin-semantics-in-ruby-1-9

Oups ! I just created a new thread on this subject.

Maybe we will get some official/more up to date position as I haven’t
found any mention on this change on the report from EigenClass “Changes
of Ruby 1.9 update 6”.

Chauk-Mean.

On 2/28/07, Pit C. [email protected] wrote:

class C < P
end

p C.ancestors # => [C, P, M, Object, Kernel]

class C
include M
end

p C.ancestors # => [C, P, M, Object, Kernel]

This has changed in 1.9 (or at least as of a few months ago which was
the last time I built 1.9)

rick@frodo:~$ cat modtest.rb
module M
end

class P
include M
end

class C < P
end

p C.ancestors

class C
include M
end

p C.ancestors

rick@frodo:~$ ruby1.8 modtest.rb
[C, P, M, Object, Kernel]
[C, P, M, Object, Kernel]
rick@frodo:~$ ruby1.9 modtest.rb
[C, P, M, Object, Kernel, BasicObject]
[C, M, P, M, Object, Kernel, BasicObject]

I wrote about this back in October
http://talklikeaduck.denhaven2.com/articles/2006/10/09/a-subtle-change-to-mixin-semantics-in-ruby-1-9


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

On 3/1/07, Ruby A. [email protected] wrote:

class C < P
rick@frodo:~$ ruby1.8 modtest.rb
[C, P, M, Object, Kernel]
[C, P, M, Object, Kernel]
rick@frodo:~$ ruby1.9 modtest.rb
[C, P, M, Object, Kernel, BasicObject]
[C, M, P, M, Object, Kernel, BasicObject]

Thanks for your reply.
This is what I expected as this is consistent with the new class var/methods behaviour.

Actually, I just checked out the latest version of the 1.9 trunk code,
and it seems to have gone back:.

rick@frodo:~$ ruby1.9 modtest.rb
[C, P, M, Object, Kernel, BasicObject]
[C, P, M, Object, Kernel, BasicObject]

I’m not sure why, personally I thought that the way 1.9 used to work
was more natural.


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/