# Identfying classes in a file dynamically

**URL:** <https://www.ruby-forum.com/t/identfying-classes-in-a-file-dynamically/57443>\
**Category:** Ruby\
**Created:** [April 11, 2006, 12:24am UTC](https://www.ruby-forum.com/t/identfying-classes-in-a-file-dynamically/57443 "2006-04-11T00:24:03Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Navya\_A](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/8baadc/32.png) [@Navya\_A](https://www.ruby-forum.com/u/Navya_A)\
**Post date:** [April 11, 2006, 12:24am UTC](https://www.ruby-forum.com/t/identfying-classes-in-a-file-dynamically/57443/1 "2006-04-11T00:24:03Z")

</div>

Hi,

I was trying to identify the classes in a give file at the run time. the  
following is the code i used.  
sc, ec = [], []  
ObjectSpace.each\_object(Class) { |c| sc \<\< c }  
require ‘Roman.rb’  
ObjectSpace.each\_object(Class) { |c| ec \<\< c }  
new\_classes = ec - sc  
puts new\_classes  
sc, ec = [], []  
ObjectSpace.each\_object(Class) { |c| sc \<\< c }  
require ‘Roman1.rb’  
ObjectSpace.each\_object(Class) { |c| ec \<\< c }  
new\_classes = ec - sc  
puts new\_classes

Both roman.rb and roman1.rb has the same class Roman.  
the first time i print the new\_classes i can see the Roman class in the  
output but the second one does not print because the class Roman is  
arleady read previously.

is there a way i can over come this problem and identify the Roman class  
twice.

Thanks,  
Navya.

---

<div class="post-metadata">

**Author:** ![Navya\_A](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/8baadc/32.png) [@Navya\_A](https://www.ruby-forum.com/u/Navya_A)\
**Post date:** [April 11, 2006, 3:29am UTC](https://www.ruby-forum.com/t/identfying-classes-in-a-file-dynamically/57443/2 "2006-04-11T03:29:49Z")

</div>

Navya A. wrote:

> ObjectSpace.each\_object(Class) { |c| sc \<\< c }  
> require ‘Roman1.rb’  
> ObjectSpace.each\_object(Class) { |c| ec \<\< c }  
> new\_classes = ec - sc  
> puts new\_classes
> 
> Both roman.rb and roman1.rb has the same class Roman.  
> the first time i print the new\_classes i can see the Roman class in the output but the second one does not print because the class Roman is arleady read previously.
> 
> is there a way i can over come this problem and identify the Roman class twice.

One way is to wrap the file in a module, so that the constants defined  
in it will not collide with other constants.

file = “some/file”  
m = Module.new  
m.module\_eval(IO.read(file), File.expand\_path(file))  
p m.constants

But then the Roman module won’t be available except as m::Roman. To fix  
this, you could include m into any class or module that needs to use  
Roman.

---

<div class="post-metadata">

**Author:** ![Navya\_A](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/8baadc/32.png) [@Navya\_A](https://www.ruby-forum.com/u/Navya_A)\
**Post date:** [April 11, 2006, 4:15am UTC](https://www.ruby-forum.com/t/identfying-classes-in-a-file-dynamically/57443/3 "2006-04-11T04:15:29Z")

</div>

Hi –

On Tue, 11 Apr 2006, Joel VanderWerf wrote:

> > sc, ec = [], []
> 
> One way is to wrap the file in a module, so that the constants defined  
> in it will not collide with other constants.
> 
> file = “some/file”  
> m = Module.new  
> m.module\_eval(IO.read(file), File.expand\_path(file))  
> p m.constants
> 
> But then the Roman module won’t be available except as m::Roman. To fix  
> this, you could include m into any class or module that needs to use Roman.

Also I think that if the read-in file uses the ::Const construct,  
those classes won’t get counted.

David

–  
David A. Black (removed\_email\_address@domain.invalid)  
Ruby Power and Light, LLC ([http://www.rubypowerandlight.com](http://www.rubypowerandlight.com))

“Ruby for Rails” coming in PDF April 15, and in paper May 5!

> **[Ruby for Rails](https://www.manning.com/books/ruby-for-rails?new=true&experiment=A)**
>
> NEWER EDITION AVAILABLE
> 
> The Well-Grounded Rubyist, Second Edition is now available. An eBook of the previous edition, The Well-Grounded Rubyist is included at no additional cost when you buy the revised edition! 
> 
> 
> Ruby for Rails helps Rails...

---

<div class="post-metadata">

**Author:** ![Navya\_A](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/8baadc/32.png) [@Navya\_A](https://www.ruby-forum.com/u/Navya_A)\
**Post date:** [April 11, 2006, 4:49am UTC](https://www.ruby-forum.com/t/identfying-classes-in-a-file-dynamically/57443/4 "2006-04-11T04:49:30Z")

</div>

Hi –

On Tue, 11 Apr 2006, Joel VanderWerf wrote:

> $ ruby -e ‘load “t.rb”; p Foo’  
> Foo  
> $ ruby -e ‘load “t.rb”; ObjectSpace.each\_object(Class) {|c| p c if  
> c.name == “Foo”}’  
> Foo
> 
> So it doesn’t look like that works, unless I’m misunderstanding…

Yes, that’s what I meant; if you have ::Foo in your file, then you  
won’t get a Foo class in the module you wrap in, so you won’t get the  
right count of modules in the file.

David

–  
David A. Black (removed\_email\_address@domain.invalid)  
Ruby Power and Light, LLC ([http://www.rubypowerandlight.com](http://www.rubypowerandlight.com))

“Ruby for Rails” coming in PDF April 15, and in paper May 5!

> **[Ruby for Rails](https://www.manning.com/books/ruby-for-rails?new=true&experiment=A)**
>
> NEWER EDITION AVAILABLE
> 
> The Well-Grounded Rubyist, Second Edition is now available. An eBook of the previous edition, The Well-Grounded Rubyist is included at no additional cost when you buy the revised edition! 
> 
> 
> Ruby for Rails helps Rails...

---

<div class="post-metadata">

**Author:** ![Navya\_A](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/8baadc/32.png) [@Navya\_A](https://www.ruby-forum.com/u/Navya_A)\
**Post date:** [April 11, 2006, 4:21am UTC](https://www.ruby-forum.com/t/identfying-classes-in-a-file-dynamically/57443/5 "2006-04-11T04:21:39Z")

</div>

removed\_email\_address@domain.invalid wrote:  
…

> Also I think that if the read-in file uses the ::Const construct,  
> those classes won’t get counted.

You mean like this:

$ cat t.rb  
class ::Foo  
end  
$ ruby -e ‘load “t.rb”; p Foo’  
Foo  
$ ruby -e ‘load “t.rb”; ObjectSpace.each\_object(Class) {|c| p c if  
c.name == “Foo”}’  
Foo

So it doesn’t look like that works, unless I’m misunderstanding…

---

<div class="post-metadata">

**Author:** ![Navya\_A](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/8baadc/32.png) [@Navya\_A](https://www.ruby-forum.com/u/Navya_A)\
**Post date:** [April 11, 2006, 5:19am UTC](https://www.ruby-forum.com/t/identfying-classes-in-a-file-dynamically/57443/6 "2006-04-11T05:19:36Z")

</div>

removed\_email\_address@domain.invalid wrote:

> > 
> 
> Yes, that’s what I meant; if you have ::Foo in your file, then you  
> won’t get a Foo class in the module you wrap in, so you won’t get the  
> right count of modules in the file.

Oh, I see–I thought you meant it was a workaround, but it’s actually a  
limitation of the module wrapping trick. Good point.

---

<div class="post-metadata">

**Author:** ![Navya\_A](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/8baadc/32.png) [@Navya\_A](https://www.ruby-forum.com/u/Navya_A)\
**Post date:** [April 11, 2006, 3:57pm UTC](https://www.ruby-forum.com/t/identfying-classes-in-a-file-dynamically/57443/7 "2006-04-11T15:57:01Z")

</div>

-----BEGIN PGP SIGNED MESSAGE-----  
Hash: SHA1

Navya A. wrote:

> ObjectSpace.each\_object(Class) { |c| sc \<\< c }

Way #1, store the new classes in a hash. This way you won’t be  
overriding any classes you’ve previously loaded.

Way #2, use one array to store new classes, and then each time you  
compute the “new\_classes” after you load a file, merge those  
into your one authoriatize array. This way you won’t be overriding any  
classes you’ve previously loaded.

Way #3, pass a string into a new ruby process which loads the files and  
outputs the new classes. Read these in and then use Way #1  
or Way #2 to store the classes. This is a bit hackish, but it works and  
it leaves your toplevel ruby process namespace alone.

Here is the idea of Way #3

str =\<\<-‘EOT’  
def count\_classes( arg )  
arr = []  
ObjectSpace.each\_object( arg ){ |c| arr \<\< c }  
arr  
end

```
orig_classes = count_classes( Class )
require "load"
new_classes = count_classes( Class ) - orig_classes
puts new_classes.join( "\n" )

```

EOT

child = IO.popen( “ruby -e ‘#{str}’”, “r” )  
new\_classes = child.readlines.map!{ |s| s.chomp! }  
puts new\_classes

Zach  
-----BEGIN PGP SIGNATURE-----  
Version: GnuPG v1.4.1 (GNU/Linux)  
Comment: Using GnuPG with Thunderbird - [http://enigmail.mozdev.org](http://enigmail.mozdev.org)

iD8DBQFEO7aRMyx0fW1d8G0RAjPQAJ0YvkXA1bRmS7VCWlxw/n5CeFUD9ACcD100  
MN9Ii+gFYzpg56Veh4YFd2g=  
=vGHj  
-----END PGP SIGNATURE-----
