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

C

Chirag Mistry

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
 
R

Robert Dober

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

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


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

Peña, Botp

T24gQmVoYWxmIE9mIENoaXJhZyBNaXN0cnk6DQojIG9ubHkgd2FudCBhIGxpc3Qgd2hpY2ggY29u
dGFpbnMgbW9kdWxlcyBNMSBhbmQgTTIgZm9yIE15Q2xhc3MuIElmIHdlDQojIGNhbGwg4oCcTXlD
bGFzcy5hbmNlc3RvcnPigJ0gd2hpY2ggcmV0dXJucyBhbGwgdGhlIG1vZHVsZXMgd2hpY2ggDQoj
IGFyZSBpbmNsdWRlIGRpcmVjdGx5IG9yIGluZGlyZWN0bHkgaW4gdGhpcyBjbGFzcyBhbmQgYWxs
IHBhcmVudCBjbGFzcyANCg0KaG93IGFib3V0IHN1YnRyYWN0aW5nIGZyIHRoZXJlID0pDQoNCnNv
bWV0aGluZyBsaWtlLCANCg0KaXJiKG1haW4pOjAyNjowPiBDMi5hbmNlc3RvcnMgLSAoQ2xhc3Mu
bmV3LmFuY2VzdG9ycyArIFtDMl0pDQo9PiBbTTIsIE0xXQ0KDQpzb3JyeSBpZiBteSBhbnN3ZXIg
c291bmQgc3R1cGlkLiANCg0Ka2luZCByZWdhcmRzIC1ib3RwDQo=
 
R

Robert Dober

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 =3D)

something like,

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

sorry if my answer sound stupid.

kind regards -botp
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
--=20
I always knew that one day Smalltalk would replace Java.
I just didn't know it would be called Ruby
-- Kent Beck
 
F

FireAphis

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

Maybe my friend irb can help ;)
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 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
 
P

Peña, Botp

From: Robert Dober [mailto:[email protected]]=20
# p C2.ancestors - (Class.new.ancestors + [C2])

yap, your scheme is more straightforward

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

F. Senault

Le 25 juillet à 08:44, (e-mail address removed) 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?

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
 
D

dohzya

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:[email protected]]
# p C2.ancestors - (Class.new.ancestors + [C2])

yap, your scheme is more straightforward

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

Peña, Botp

From: Pe=F1a, Botp [mailto:[email protected]]=20
# From: Robert Dober [mailto:[email protected]]=20
# # p C2.ancestors - (Class.new.ancestors + [C2])
#=20
# yap, your scheme is more straightforward
#=20
# (C.ancestors-[Kernel]).select{|x| x.class =3D=3D Module}

i forgot one,

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

Robert Dober

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

Maybe my friend irb can help ;)
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 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 :)
 
P

Peña, Botp

From: Robert Dober [mailto:[email protected]]=20
# > I think that Chirag wanted to get only M2 and as you can=20
# see we get M1 as well.
# What!!! Do I have to read the post in oder to answer now???
#=20
# My bad you are right indeed.
#=20
# > 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=20
# this matter?
# That is indeed more challenging :)

FredSenault's previous post should give a hint

kind regards -botp
 
D

dohzya

Le mercredi 25 juillet 2007 à 18:24 +0900, Robert Dober a écrit :
How about (C2.ancestors - [C2] - C2.superclass.ancestors) ?
You got it, indeed it was not so chellanging after all :(


Cheers
Robert

There is a problem :
---
module M1 ; end
module M2 ; end
class C1 ; include M1 ; end
class C2 < C1 ; include M1 ; include M2 ; end

p (C2.ancestors - [C2] - C2.superclass.ancestors) # => [M2]
 
R

Robert Dober

Le mercredi 25 juillet 2007 =E0 18:24 +0900, Robert Dober a =E9crit :
How about (C2.ancestors - [C2] - C2.superclass.ancestors) ?
You got it, indeed it was not so chellanging after all :(


Cheers
Robert

There is a problem :
---
module M1 ; end
module M2 ; end
class C1 ; include M1 ; end
class C2 < C1 ; include M1 ; include M2 ; end

p (C2.ancestors - [C2] - C2.superclass.ancestors) # =3D> [M2]
We have to ask OP, if he really wants to have M1 in this list I am
afraid that Fred's metaprogramming track by using Module#included is
the only way,
maybe it would be nice if OP could tell us what this is for.Cheers
Robert

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

FireAphis

Le mercredi 25 juillet 2007 à 18:24 +0900, Robert Dober a écrit :
How about (C2.ancestors - [C2] - C2.superclass.ancestors) ?
You got it, indeed it was not so chellanging after all :(
Cheers
Robert

There is a problem :
---
module M1 ; end
module M2 ; end
class C1 ; include M1 ; end
class C2 < C1 ; include M1 ; include M2 ; end

p (C2.ancestors - [C2] - C2.superclass.ancestors) # => [M2]

There is another problem. If C2 doesn't inherit another class but does
include the modules and those modules by themselves include modules
then your code, still, will return the whole hierarchy. Look at this:

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

p (C2.ancestors - [C2] - C2.superclass.ancestors) # => [M1, M2]

That's because C2.superclass => Object

:(

FireAphis
 
D

dohzya

Le mercredi 25 juillet 2007 à 20:04 +0900, FireAphis a écrit :
There is another problem. If C2 doesn't inherit another class but does
include the modules and those modules by themselves include modules
then your code, still, will return the whole hierarchy. Look at this:

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

p (C2.ancestors - [C2] - C2.superclass.ancestors) # => [M1, M2]

That's because C2.superclass => Object

:(

FireAphis

You're right, but it can be fixed :)
---
class Class
def included_modules
c = self
all = c.ancestors - [c]
bad = all.map {|a|
a.ancestors - [a]
}
# Module#superclass doesn't exist
bad << c.superclass if c.is_a? Class
all - bad.flatten
end
end

module M1; end
module M2; include M1; end
module M3; end
module M4; include M3; end
module M5; end
module M6; include M5; end
module M7; end
class C1; include M2; end
class C2<C1; include M4; end
class C3<C2; include M6; include M7; end

p C3.included_modules # => [M7, M6]
 
F

F. Senault

Le 25 juillet à 11:32, Peña, Botp a écrit :
FredSenault's previous post should give a hint

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

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
 
R

Robert Dober

Le mercredi 25 juillet 2007 =E0 20:04 +0900, FireAphis a =E9crit :
There is another problem. If C2 doesn't inherit another class but does
include the modules and those modules by themselves include modules
then your code, still, will return the whole hierarchy. Look at this:

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

p (C2.ancestors - [C2] - C2.superclass.ancestors) # =3D> [M1, M2]

That's because C2.superclass =3D> Object

:(

FireAphis

You're right, but it can be fixed :)
no it cannot :(, look at C4 below
---
class Class
def included_modules
c =3D self
all =3D c.ancestors - [c]
bad =3D all.map {|a|
a.ancestors - [a]
}
# Module#superclass doesn't exist
bad << c.superclass if c.is_a? Class
all - bad.flatten
end
end

module M1; end
module M2; include M1; end
module M3; end
module M4; include M3; end
module M5; end
module M6; include M5; end
module M7; end
class C1; include M2; end
class C2<C1; include M4; end
class C3<C2; include M6; include M7; end
class C4<C2; include M5; include M6; end
*************************************
M5 will not show up.


p C3.included_modules # =3D> [M7, M6]


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

dohzya

Le mercredi 25 juillet 2007 à 22:58 +0900, Robert Dober a écrit :
You're right, but it can be fixed :)
no it cannot :(, look at C4 below
---
class Class
def included_modules
c = self
all = c.ancestors - [c]
bad = all.map {|a|
a.ancestors - [a]
}
# Module#superclass doesn't exist
bad << c.superclass if c.is_a? Class
all - bad.flatten
end
end

module M1; end
module M2; include M1; end
module M3; end
module M4; include M3; end
module M5; end
module M6; include M5; end
module M7; end
class C1; include M2; end
class C2<C1; include M4; end
class C3<C2; include M6; include M7; end
class C4<C2; include M5; include M6; end
*************************************
M5 will not show up.

This was the first and not fixable (with this solution) problem :)
module re-included are hidden

---
module M1; end
module M2; end
module M3; include M2; end
class C1; include M1; end
class C2 < C1; include M1; include M2; include M3; end
 
R

Robert Dober

Le mercredi 25 juillet 2007 =E0 22:58 +0900, Robert Dober a =E9crit :
You're right, but it can be fixed :)
no it cannot :(, look at C4 below
---
class Class
def included_modules
c =3D self
all =3D c.ancestors - [c]
bad =3D all.map {|a|
a.ancestors - [a]
}
# Module#superclass doesn't exist
bad << c.superclass if c.is_a? Class
all - bad.flatten
end
end

module M1; end
module M2; include M1; end
module M3; end
module M4; include M3; end
module M5; end
module M6; include M5; end
module M7; end
class C1; include M2; end
class C2<C1; include M4; end
class C3<C2; include M6; include M7; end
class C4<C2; include M5; include M6; end
*************************************
M5 will not show up.

This was the first and not fixable (with this solution) problem :)
module re-included are hidden

---
module M1; end
module M2; end
module M3; include M2; end
class C1; include M1; end
class C2 < C1; include M1; include M2; include M3; end
yeah the information just is not in the ancestor array :(
but it was a nice try ;)

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

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,997
Messages
2,570,240
Members
46,830
Latest member
HeleneMull

Latest Threads

Top