How to get modules included by a class/module (not those from the superclasses)

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.

···

---------------------------------
Need Mail bonding?
Go to the Yahoo! Mail Q&A for great tips from Yahoo! Answers users.

Ruby Admirer 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.

···

---------------------------------
Don't be flakey. Get Yahoo! Mail for Mobile and
always stay connected to friends.

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]
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

···

On 2/28/07, Pit Capitain <pit@capitain.de> wrote:

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]

--
Rick DeNatale

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

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]

  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.

···

---------------------------------
Need a quick answer? Get one in minutes from people who know. Ask your question on Yahoo! Answers.

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]

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

···

On 3/1/07, Ruby Admirer <ruby_admirer@yahoo.com> wrote:

>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]
>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.

--
Rick DeNatale

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