Help: Get list of modules which are included in the class

Hi

I want to get a list of modules which are included directly in the class
in ruby. Example: Suppose below are two modules and a class defined in
ruby script.

···

-------------------
module M1
  …
end
module M2
  …
end
class MyClass
  include M1
  include M2
  …
end
-------------------
How can I get list of modules which are included directly in the class?
Here in above example, M1 and M2 are only included in class MyClass so I
only want a list which contains modules M1 and M2 for MyClass. If we
call “MyClass.ancestors” which returns all the modules which are include
directly or indirectly in this class and all parent class hierarchy that
exactly I don’t want to get.

Regards
Chirag
--
Posted via http://www.ruby-forum.com/.

Maybe my friend irb can help :wink:
irb(main):001:0> module M1; end
=> nil
irb(main):002:0> class C1; include M1 end
=> C1
irb(main):003:0> module M2; end
=> nil
irb(main):004:0> class C2 < C1; include M2 end
=> C2
irb(main):017:0> class Module
irb(main):018:1> def included_modules
irb(main):019:2> ancestors.select{|x|x.class==Module}
irb(main):020:2> end
irb(main):021:1> end
irb(main):022:0> C1.included_modules
=> [M1, Kernel]
irb(main):023:0> C2.included_modules
=> [M2, M1, Kernel]

You can get of Kernel of course if you do not want it to show up at the party.
HTH
Robert

···

On 7/25/07, Chirag Mistry <chirag80bece@gmail.com> wrote:

Hi

I want to get a list of modules which are included directly in the class
in ruby. Example: Suppose below are two modules and a class defined in
ruby script.
-------------------
module M1
  …
end
module M2
  …
end
class MyClass
  include M1
  include M2
  …
end
-------------------
How can I get list of modules which are included directly in the class?
Here in above example, M1 and M2 are only included in class MyClass so I
only want a list which contains modules M1 and M2 for MyClass. If we
call "MyClass.ancestors" which returns all the modules which are include
directly or indirectly in this class and all parent class hierarchy that
exactly I don't want to get.

Regards
Chirag
--
Posted via http://www.ruby-forum.com/\.

--
I always knew that one day Smalltalk would replace Java.
I just didn't know it would be called Ruby
-- Kent Beck

On Behalf Of Chirag Mistry:
# only want a list which contains modules M1 and M2 for MyClass. If we
# call “MyClass.ancestors” which returns all the modules which
# are include directly or indirectly in this class and all parent class

how about subtracting fr there =)

something like,

irb(main):026:0> C2.ancestors - (Class.new.ancestors + [C2])
=> [M2, M1]

sorry if my answer sound stupid.

kind regards -botp

Chirag,

This is how I handle it in my applications:

# lib/ruby_extensions.rb

···

=======================================
class Module
   def included_modules
     ( ancestors - [ Kernel ] ).select { | x | x.class == Module && x != Kernel }
   end

   def directly_included_modules
     ancestors - superclass.ancestors - [self]
   end

   def inherited_modules
     superclass.included_modules - self.directly_included_modules
   end
end

=======================================
irb:

>> module Module1; end
   =>nil

>> class Class1; include Module1 end
   =>Class1

>> module Module2; end
   =>nil

>> class Class2 < Class1; include Module2 end
   =>Class2

>> Class1.included_modules
   =>[Module1]

>> Class2.included_modules
   =>[Module2, Module1]

>> Class1.directly_included_modules
   =>[Module1]

>> Class2.directly_included_modules
   =>[Module2]

>> Class1.inherited_modules
   =>[]

>> Class2.inherited_modules
   =>[Module1]

Actually, I also allow for filtering out of other modules than Kernel but that's not relevant here.

I sincerely hope this helps.

=======================================
(easy irb example paste:)

module Module1; end
class Class1; include Module1 end
module Module2; end
class Class2 < Class1; include Module2 end

Class1.included_modules
Class2.included_modules

Class1.directly_included_modules
Class2.directly_included_modules

Class1.inherited_modules
Class2.inherited_modules

--
Wayne E. Seguin
Sr. Systems Architect & Systems Admin
wayneseguin@gmail.com

not stupid at all, you just overlooked a little detail, parent classes.

module M1; end
module M2; end
class C1; include M1 end
class C2 < C1; include M2 end

p C2.ancestors - (Class.new.ancestors + [C2])

Robert

···

On 7/25/07, Peña, Botp <botp@delmonte-phil.com> wrote:

On Behalf Of Chirag Mistry:
# only want a list which contains modules M1 and M2 for MyClass. If we
# call "MyClass.ancestors" which returns all the modules which
# are include directly or indirectly in this class and all parent class

how about subtracting fr there =)

something like,

irb(main):026:0> C2.ancestors - (Class.new.ancestors + [C2])
=> [M2, M1]

sorry if my answer sound stupid.

kind regards -botp

--
I always knew that one day Smalltalk would replace Java.
I just didn't know it would be called Ruby
-- Kent Beck

I don't think that it answers the question. Look at the following
example:

irb(main):120:0> module M1
irb(main):121:1> end
=> nil
irb(main):122:0> module M2
irb(main):123:1> include M1
irb(main):124:1> end
=> M2
irb(main):125:0> class C1
irb(main):126:1> include M2
irb(main):127:1> end
=> C1
irb(main):128:0> C1.ancestors.select{|x|x.class==Module}
=> [M2, M1, Kernel]

I think that Chirag wanted to get only M2 and as you can see we get M1
as well. I personally think that there is no way to solve this. As far
as I know Ruby holds its ancestors internally in a plain list and
doesn't remember the hierarchy. Can someone tell more on this matter?

FireAphis

···

On Jul 25, 11:21 am, "Robert Dober" <robert.do...@gmail.com> wrote:

On 7/25/07, Chirag Mistry <chirag80b...@gmail.com> wrote:

> Hi

> I want to get a list of modules which are included directly in the class
> in ruby. Example: Suppose below are two modules and a class defined in
> ruby script.
> -------------------
> module M1
> ...
> end
> module M2
> ...
> end
> class MyClass
> include M1
> include M2
> ...
> end
> -------------------
> How can I get list of modules which are included directly in the class?
> Here in above example, M1 and M2 are only included in class MyClass so I
> only want a list which contains modules M1 and M2 for MyClass. If we
> call "MyClass.ancestors" which returns all the modules which are include
> directly or indirectly in this class and all parent class hierarchy that
> exactly I don't want to get.

> Regards
> Chirag
> --
> Posted viahttp://www.ruby-forum.com/.

Maybe my friend irb can help :wink:
irb(main):001:0> module M1; end
=> nil
irb(main):002:0> class C1; include M1 end
=> C1
irb(main):003:0> module M2; end
=> nil
irb(main):004:0> class C2 < C1; include M2 end
=> C2
irb(main):017:0> class Module
irb(main):018:1> def included_modules
irb(main):019:2> ancestors.select{|x|x.class==Module}
irb(main):020:2> end
irb(main):021:1> end
irb(main):022:0> C1.included_modules
=> [M1, Kernel]
irb(main):023:0> C2.included_modules
=> [M2, M1, Kernel]

You can get of Kernel of course if you do not want it to show up at the party.
HTH
Robert

--
I always knew that one day Smalltalk would replace Java.
I just didn't know it would be called Ruby
-- Kent Beck

There is a problem (him ! again ! Arrrrrrg (Monthy Python dixit (yeah
for Monthy Ruby !!! (sorry, I'll try to stop lisp-mod ;)))))
You should try this :

···

Le mercredi 01 août 2007 à 05:44 +0900, Wayne E. Seguin a écrit :

Chirag,

This is how I handle it in my applications:

# lib/ruby_extensions.rb

class Module
   def included_modules
     ( ancestors - [ Kernel ] ).select { | x | x.class == Module &&
x != Kernel }
   end

   def directly_included_modules
     ancestors - superclass.ancestors - [self]
   end

   def inherited_modules
     superclass.included_modules - self.directly_included_modules
   end
end

=======================================
irb:

>> module Module1; end
   =>nil

>> class Class1; include Module1 end
   =>Class1

>> module Module2; end
   =>nil

>> class Class2 < Class1; include Module2 end
   =>Class2

>> Class1.included_modules
   =>[Module1]

>> Class2.included_modules
   =>[Module2, Module1]

>> Class1.directly_included_modules
   =>[Module1]

>> Class2.directly_included_modules
   =>[Module2]

>> Class1.inherited_modules
   =>

>> Class2.inherited_modules
   =>[Module1]

Actually, I also allow for filtering out of other modules than Kernel
but that's not relevant here.

I sincerely hope this helps.

=======================================
(easy irb example paste:)

module Module1; end
class Class1; include Module1 end
module Module2; end
class Class2 < Class1; include Module2 end

Class1.included_modules
Class2.included_modules

Class1.directly_included_modules
Class2.directly_included_modules

Class1.inherited_modules
Class2.inherited_modules

--
Wayne E. Seguin
Sr. Systems Architect & Systems Admin
wayneseguin@gmail.com

---
module Module1; end
class Class1; include Module1 end
module Module2; end
class Class2 < Class1; include Module1 ; include Module2 end

Class1.included_modules
Class2.included_modules

Class1.directly_included_modules
Class2.directly_included_modules # see this result

Class1.inherited_modules
Class2.inherited_modules
---

--
Etienne Vallette d'Osia

# p C2.ancestors - (Class.new.ancestors + [C2])

yap, your scheme is more straightforward

(C.ancestors-[Kernel]).select{|x| x.class == Module}

···

From: Robert Dober [mailto:robert.dober@gmail.com]

You can always build the list yourself :

#! /usr/local/bin/ruby

class Module
  attr_accessor :children
  def included(c)
    @children ||=
    @children << c
  end
end

module M1
end

module M2
  include M1
end

class C1
  include M2
end

class C2 < C1
  include M2
end

C1.ancestors.each { |x| puts "#{x} : #{x.children.inspect}" }

p C1.ancestors.select { |x| x.instance_of?(Module) && x.children && x.children.include?(C1) }

Gives :

C1 : nil
M2 : [C1, C2]
M1 : [M2]
Object : nil
Kernel : nil
[M2]

(Not very much tested, but the idea is there, I think.)

Fred

···

Le 25 juillet à 08:44, FireAphis@gmail.com a écrit :

I think that Chirag wanted to get only M2 and as you can see we get M1
as well. I personally think that there is no way to solve this. As far
as I know Ruby holds its ancestors internally in a plain list and
doesn't remember the hierarchy. Can someone tell more on this matter?

--
I can imagine the moment Breaking out through the silence All the
things that we both might say And the heart it will not be denied
'Til we're both on the same damn side All the barriers blown away
                                        (Peter Gabriel, Come Talk to Me)

>
> > Hi
>
> > I want to get a list of modules which are included directly in the class
> > in ruby. Example: Suppose below are two modules and a class defined in
> > ruby script.
> > -------------------
> > module M1
> > ...
> > end
> > module M2
> > ...
> > end
> > class MyClass
> > include M1
> > include M2
> > ...
> > end
> > -------------------
> > How can I get list of modules which are included directly in the class?
> > Here in above example, M1 and M2 are only included in class MyClass so I
> > only want a list which contains modules M1 and M2 for MyClass. If we
> > call "MyClass.ancestors" which returns all the modules which are include
> > directly or indirectly in this class and all parent class hierarchy that
> > exactly I don't want to get.
>
> > Regards
> > Chirag
> > --
> > Posted viahttp://www.ruby-forum.com/.
>
> Maybe my friend irb can help :wink:
> irb(main):001:0> module M1; end
> => nil
> irb(main):002:0> class C1; include M1 end
> => C1
> irb(main):003:0> module M2; end
> => nil
> irb(main):004:0> class C2 < C1; include M2 end
> => C2
> irb(main):017:0> class Module
> irb(main):018:1> def included_modules
> irb(main):019:2> ancestors.select{|x|x.class==Module}
> irb(main):020:2> end
> irb(main):021:1> end
> irb(main):022:0> C1.included_modules
> => [M1, Kernel]
> irb(main):023:0> C2.included_modules
> => [M2, M1, Kernel]
>
> You can get of Kernel of course if you do not want it to show up at the party.
> HTH
> Robert
>
> --
> I always knew that one day Smalltalk would replace Java.
> I just didn't know it would be called Ruby
> -- Kent Beck

I don't think that it answers the question. Look at the following
example:

irb(main):120:0> module M1
irb(main):121:1> end
=> nil
irb(main):122:0> module M2
irb(main):123:1> include M1
irb(main):124:1> end
=> M2
irb(main):125:0> class C1
irb(main):126:1> include M2
irb(main):127:1> end
=> C1
irb(main):128:0> C1.ancestors.select{|x|x.class==Module}
=> [M2, M1, Kernel]

I think that Chirag wanted to get only M2 and as you can see we get M1
as well.

What!!! Do I have to read the post in oder to answer now???

My bad you are right indeed.

I personally think that there is no way to solve this. As far
as I know Ruby holds its ancestors internally in a plain list and
doesn't remember the hierarchy. Can someone tell more on this matter?

That is indeed more challenging :slight_smile:

···

On 7/25/07, FireAphis@gmail.com <FireAphis@gmail.com> wrote:

On Jul 25, 11:21 am, "Robert Dober" <robert.do...@gmail.com> wrote:
> On 7/25/07, Chirag Mistry <chirag80b...@gmail.com> wrote:

FireAphis

--
I always knew that one day Smalltalk would replace Java.
I just didn't know it would be called Ruby
-- Kent Beck

Etienne,

Good point. Any ideas on a better way?
Although if you're including twice like that the design is most likely flawed and needs a re-factoring?

···

On Aug 01, 2007, at 08:56 , dohzya wrote:

There is a problem (him ! again ! Arrrrrrg (Monthy Python dixit (yeah
for Monthy Ruby !!! (sorry, I'll try to stop lisp-mod ;)))))
You should try this :
---
module Module1; end
class Class1; include Module1 end
module Module2; end
class Class2 < Class1; include Module1 ; include Module2 end

Class1.included_modules
Class2.included_modules

Class1.directly_included_modules
Class2.directly_included_modules # see this result

Class1.inherited_modules
Class2.inherited_modules
---

--
Etienne Vallette d'Osia

--
Wayne E. Seguin
Sr. Systems Architect & Systems Admin
wayneseguin@gmail.com

Etienne,

Thank you very much for this feedback. After thinking about it, here is my take on this:

We include Module1 in Class1 and so from inheritence this implies that Class2 does not actually include Module1 directly, since it has already been included. Hence including Module1 in Class2 is effectively a no-op.

This makes semantic sense, also: "directly_included_modules" should be the modules that self includes which the superclass does not. In this light Module1 is not directly included so my code does what is expected.

(Also, for the record, Module already has an included_modules method, but I am overwriting because I don't want Kernel listed for my purposes)

(Thanks to Mark Josef for helping me with this idea)

···

On Aug 01, 2007, at 08:56 , dohzya wrote:

Le mercredi 01 août 2007 à 05:44 +0900, Wayne E. Seguin a écrit :

<snip>

There is a problem (him ! again ! Arrrrrrg (Monthy Python dixit (yeah
for Monthy Ruby !!! (sorry, I'll try to stop lisp-mod ;)))))
You should try this :
---
module Module1; end
class Class1; include Module1 end
module Module2; end
class Class2 < Class1; include Module1 ; include Module2 end

Class1.included_modules
Class2.included_modules

Class1.directly_included_modules
Class2.directly_included_modules # see this result

Class1.inherited_modules
Class2.inherited_modules
---

--
Etienne Vallette d'Osia

--
Wayne E. Seguin
Sr. Systems Architect & Systems Admin
wayneseguin@gmail.com

How about (C2.ancestors - [C2] - C2.superclass.ancestors) ?

···

Le mercredi 25 juillet 2007 à 17:54 +0900, Peña, Botp a écrit :

From: Robert Dober [mailto:robert.dober@gmail.com]
# p C2.ancestors - (Class.new.ancestors + [C2])

yap, your scheme is more straightforward

(C.ancestors-[Kernel]).select{|x| x.class == Module}

--
Etienne Vallette d'Osia

# From: Robert Dober [mailto:robert.dober@gmail.com]
# # p C2.ancestors - (Class.new.ancestors + [C2])

···

From: Peña, Botp [mailto:botp@delmonte-phil.com]
#
# yap, your scheme is more straightforward
#
# (C.ancestors-[Kernel]).select{|x| x.class == Module}

i forgot one,

irb(main):044:0> C.included_modules
=> [M2, M1, Kernel]
irb(main):046:0> C3.included_modules - [Kernel]
=> [M2, M1]

# > I think that Chirag wanted to get only M2 and as you can
# see we get M1 as well.
# What!!! Do I have to read the post in oder to answer now???

···

From: Robert Dober [mailto:robert.dober@gmail.com]
# On 7/25/07, FireAphis@gmail.com <FireAphis@gmail.com> wrote:
#
# My bad you are right indeed.
#
# > I personally think that there is no way to solve this. As far
# > as I know Ruby holds its ancestors internally in a plain list and
# > doesn't remember the hierarchy. Can someone tell more on
# this matter?
# That is indeed more challenging :slight_smile:

FredSenault's previous post should give a hint

kind regards -botp

Peña, Botp wrote:

From: Robert Dober [mailto:robert.dober@gmail.com]
# p C2.ancestors - (Class.new.ancestors + [C2])

Hi

Thanks for the reply. I have looked all the solution but all above
solution also includes modules which are included indirectly. I wants
list of modules which are included directly. See below example.

E.g.

···

----
module IN
end

module M1
  include IN
end

module M2
  include IN
end

class C
  include M1
  include M2
  ...
end
----
     If we try above solution then I will get M1, M2, IN and Kernel. But
I want list which contains M1 and M2 only because these both are
included directly in class C.

Regards
Chirag
--
Posted via http://www.ruby-forum.com/\.

Etienne,

Thank you very much for this feedback. After thinking about it, here
is my take on this:

We include Module1 in Class1 and so from inheritence this implies
that Class2 does not actually include Module1 directly, since it has
already been included. Hence including Module1 in Class2 is
effectively a no-op.

This makes semantic sense, also: "directly_included_modules" should
be the modules that self includes which the superclass does not. In
this light Module1 is not directly included so my code does what is
expected.

(Also, for the record, Module already has an included_modules method,
but I am overwriting because I don't want Kernel listed for my purposes)

(Thanks to Mark Josef for helping me with this idea)

--
Wayne E. Seguin
Sr. Systems Architect & Systems Admin
wayneseguin@gmail.com

Thanks :blush:
Indeed, it's comparable with the difference between 'define' and
'overload' (it isn't?)... moreover it's an overloading with same
method(s) :slight_smile:
(I'm sorry if I'm repeating anyone, it's hard for me to express myself
and understand correctly in English... I'm working in this way)

···

--
Etienne Vallette d'Osia

You got it, indeed it was not so chellanging after all :frowning:

Cheers
Robert

···

On 7/25/07, dohzya <dohzya@gmail.com> wrote:

How about (C2.ancestors - [C2] - C2.superclass.ancestors) ?

--
I always knew that one day Smalltalk would replace Java.
I just didn't know it would be called Ruby
-- Kent Beck

Just Fred is all right, y'know... :slight_smile:

But this is just to say I missed the obvious with meta-programming
inside the Module class :

class Module
  alias orig_include include
  def directly_included_modules
    @d_i_m ||
  end
  def include(m)
    @d_i_m ||=
    @d_i_m << m
    orig_include m
  end
end

(Maybe some 'freeze'ing could be in order, too.)

Fred

···

Le 25 juillet à 11:32, Peña, Botp a écrit :

FredSenault's previous post should give a hint

--
Love, I don't like to see so much pain So much wasted and this moment
keeps slipping away I get so tired of working so hard for out survival
I look to the time with you to keep me awake and alive
                                           (Peter Gabriel, In Your Eyes)

# Peña, Botp wrote:
# > From: Robert Dober [mailto:robert.dober@gmail.com]
# > # p C2.ancestors - (Class.new.ancestors + [C2])
# E.g.
# ----
# module IN
# end

···

From: Chirag Mistry [mailto:chirag80bece@gmail.com]
#
# module M1
# include IN
# end
#
# module M2
# include IN
# end
#
# class C
# include M1
# include M2
# ...
# end
# ----
# If we try above solution then I will get M1, M2, IN and
# Kernel. But
# I want list which contains M1 and M2 only because these both are
# included directly in class C.

again, you can do fred's technique or

you can do plain subtraction. get the included modules of each and subtract it from the main...

something like,

irb(main):059:0* M1.included_modules
=> [IN]
irb(main):060:0> M2.included_modules
=> [IN]
irb(main):061:0> IN.included_modules
=> []

....
irb(main):055:0> mymodules = C.included_modules - [Kernel]
=> [M2, M1, IN]
irb(main):056:0> mymodules.each {|m| mymodules -= m.included_modules}
=> [M2, M1, IN]
irb(main):057:0> mymodules
=> [M2, M1]

kind regards -botp