# Get all classes from a list of files

**URL:** https://rubytalk.org/t/get-all-classes-from-a-list-of-files/63713
**Category:** ruby-talk
**Created:** [28 September 2011 12:33 UTC](https://rubytalk.org/t/get-all-classes-from-a-list-of-files/63713 "2011-09-28T12:33:16Z")
**Posts on this page:** 11
**Page:** 1

<div class="post-metadata">

### Author: ![Jeroen\_v](https://avatars.discourse-cdn.com/v4/letter/j/bc8723/32.png) [@Jeroen\_v](https://rubytalk.org/u/Jeroen_v)
#### Post date: [28 September 2011 12:33 UTC](https://rubytalk.org/t/get-all-classes-from-a-list-of-files/63713/1 "2011-09-28T12:33:16Z")

</div>

I have a list of ruby files. I would like to create objects from all  
classes using eval(classname)

My filelist looks something like:  
nl/foo\_nl\_bar.rb #class NL::FooNLBar  
en/bar\_en\_foo.rb #class EN::BarENFoo

For now my solution is as follows:  
File.readlines(rubyfile).find\_all{|line|  
line.start\_with?("class")}.collect{|file|  
file.split("\<")[0].gsub(/class/, "")}.map(&:strip)

IMHO this is ugly

I tried doing it with Module.constants. It returns the classnames, but  
the namespace is missing.  
Using String.camelize.constantize returns BarEnFoo. So here the  
namespace is also missing and the camelize doesn't work.

Doe anyone know a cleaner solution?

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

### Author: ![Josh\_Cheek](https://avatars.discourse-cdn.com/v4/letter/j/e79b87/32.png) [@Josh\_Cheek](https://rubytalk.org/u/Josh_Cheek)
#### Post date: [28 September 2011 13:12 UTC](https://rubytalk.org/t/get-all-classes-from-a-list-of-files/63713/2 "2011-09-28T13:12:26Z")

</div>

If you follow common conventions, you can infer class names from filenames.

What problem are you trying to solve? What if, instead of scraping files and  
evaling strings, you had the classes register themselves with whatever needs  
these instances? Here is an example:

This class needs to know about all of my interfaces

> <https://github.com/JoshCheek/ttt/blob/1b10b6ac18ccf066d992abdc12ec6e43acf55f08/lib/ttt/interface.rb>

So when they are defined, they tell the class that they exist

> <https://github.com/JoshCheek/ttt/blob/1b10b6ac18ccf066d992abdc12ec6e43acf55f08/lib/ttt/interface/cli.rb#L7>

> <https://github.com/JoshCheek/ttt/blob/1b10b6ac18ccf066d992abdc12ec6e43acf55f08/lib/ttt/interface/limelight.rb#L7>

> **···**
>
> On Wed, Sep 28, 2011 at 7:33 AM, Jeroen van Ingen \<jeroeningen@gmail.com\>wrote:
> 
> > I have a list of ruby files. I would like to create objects from all  
> > classes using eval(classname)
> > 
> > My filelist looks something like:  
> > nl/foo\_nl\_bar.rb #class NL::FooNLBar  
> > en/bar\_en\_foo.rb #class EN::BarENFoo
> > 
> > For now my solution is as follows:  
> > File.readlines(rubyfile).find\_all{|line|  
> > line.start\_with?("class")}.collect{|file|  
> > file.split("\<")[0].gsub(/class/, "")}.map(&:strip)
> > 
> > IMHO this is ugly
> > 
> > I tried doing it with Module.constants. It returns the classnames, but  
> > the namespace is missing.  
> > Using String.camelize.constantize returns BarEnFoo. So here the  
> > namespace is also missing and the camelize doesn't work.
> > 
> > Doe anyone know a cleaner solution?
> > 
> > --  
> > Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

### Author: ![Jeroen\_v](https://avatars.discourse-cdn.com/v4/letter/j/bc8723/32.png) [@Jeroen\_v](https://rubytalk.org/u/Jeroen_v)
#### Post date: [28 September 2011 13:45 UTC](https://rubytalk.org/t/get-all-classes-from-a-list-of-files/63713/3 "2011-09-28T13:45:03Z")

</div>

My problem is that when I add a file to the files, it must be  
automatically included in the list of classes, so I can create an object  
like I said; eval(classname)

Your solution is ugly for me in another way. Let me explain...  
All my files are included in the same dir and subdirs. So it's not  
needed to tell every single file that it must register itself. I would  
like to it in one place, not in every single file.

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

### Author: ![Hans\_Mackowiak](https://avatars.discourse-cdn.com/v4/letter/h/f08c70/32.png) [@Hans\_Mackowiak](https://rubytalk.org/u/Hans_Mackowiak)
#### Post date: [28 September 2011 14:27 UTC](https://rubytalk.org/t/get-all-classes-from-a-list-of-files/63713/4 "2011-09-28T14:27:59Z")

</div>

sorry but why did you want to use eval?  
eval is allways the badest possible code

use Object.const\_get(classname).new

or if the classname include "::" do this  
classname.split("::").inject(Object,:const\_get).new

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

### Author: ![Jeroen\_v](https://avatars.discourse-cdn.com/v4/letter/j/bc8723/32.png) [@Jeroen\_v](https://rubytalk.org/u/Jeroen_v)
#### Post date: [1 October 2011 16:05 UTC](https://rubytalk.org/t/get-all-classes-from-a-list-of-files/63713/5 "2011-10-01T16:05:19Z")

</div>

@Adam  
I'm not talking about inheritance. I just want to get access to all  
ruby-classes inside a list of files in a dir and it subdirs.

@Hans  
Ah OK, thanks. I thought eval() was the only way to do it.  
Can you explain why eval() is always the badest solution?

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

### Author: ![luke\_gruber](https://avatars.discourse-cdn.com/v4/letter/l/3d9bf3/32.png) [@luke\_gruber](https://rubytalk.org/u/luke_gruber)
#### Post date: [2 October 2011 00:17 UTC](https://rubytalk.org/t/get-all-classes-from-a-list-of-files/63713/6 "2011-10-02T00:17:04Z")

</div>

> Jeroen van Ingen wrote in post #1024064:

> I have a list of ruby files. I would like to create objects from all  
> Classes

> Does anyone know a cleaner solution?

Module.nesting returns the fully namespaced modules beneath wherever it  
was called, so something like this maybe?

mod.module\_eval do  
&nbsp;&nbsp;Module.nesting.select {|m| m.is\_a? Class}  
end

Hope this helps,

-Luke

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

### Author: ![Adam\_Hegge](https://avatars.discourse-cdn.com/v4/letter/a/df705f/32.png) [@Adam\_Hegge](https://rubytalk.org/u/Adam_Hegge)
#### Post date: [28 September 2011 14:13 UTC](https://rubytalk.org/t/get-all-classes-from-a-list-of-files/63713/7 "2011-09-28T14:13:16Z")

</div>

Jeroen van Ingen wrote in post #1024083:

> My problem is that when I add a file to the files, it must be  
> automatically included in the list of classes, so I can create an object  
> like I said; eval(classname)
> 
> Your solution is ugly for me in another way. Let me explain...  
> All my files are included in the same dir and subdirs. So it's not  
> needed to tell every single file that it must register itself. I would  
> like to it in one place, not in every single file.

possibly something like this??

[http://pastebin.com/fnZkJp3L](http://pastebin.com/fnZkJp3L)

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

### Author: ![Phillip\_Gawlowski](https://avatars.discourse-cdn.com/v4/letter/p/ecc23a/32.png) [@Phillip\_Gawlowski](https://rubytalk.org/u/Phillip_Gawlowski)
#### Post date: [1 October 2011 16:56 UTC](https://rubytalk.org/t/get-all-classes-from-a-list-of-files/63713/8 "2011-10-01T16:56:12Z")

</div>

eval('system "rm -rf /"') # Where'd my UNIX go?

> **···**
>
> On Sat, Oct 1, 2011 at 6:05 PM, Jeroen van Ingen \<jeroeningen@gmail.com\> wrote:
> 
> > Can you explain why eval() is always the badest solution?
> 
> --  
> Phillip Gawlowski
> 
> gplus.to/phgaw | twitter.com/phgaw
> 
> A method of solution is perfect if we can forsee from the start,  
> and even prove, that following that method we shall attain our aim.  
> -- Leibniz

---

<div class="post-metadata">

### Author: ![Josh\_Cheek](https://avatars.discourse-cdn.com/v4/letter/j/e79b87/32.png) [@Josh\_Cheek](https://rubytalk.org/u/Josh_Cheek)
#### Post date: [1 October 2011 20:37 UTC](https://rubytalk.org/t/get-all-classes-from-a-list-of-files/63713/9 "2011-10-01T20:37:29Z")

</div>

This is seriously the wrong approach. It hides what's actually happening, is  
very difficult to do correctly, and it can easily cause lots of unrelated  
code to break. I will again recommend having the class just tell the  
instantiator that it exists and conforms to the expectations of the  
instantiator. You could do it the way I showed or the way Adam showed.

There might be other solutions too, this is just how I handled it in the  
past. But grepping files to construct a string you can evaluate is  
definitely the wrong thing to do:

## Problem 1: Due to its indiscriminate instantiation, your code will be  
fragile and rigid ##

What happens if you have some code that should go in that directory, but the  
class shouldn't be instantiated by your code? How will you distinguish?

What if you reopen a class, then it will get instantiated twice! You'll have  
to go hack on the parsing code to track how many times its instantiated each  
class `class MyClass; end; class MyClass; end`

What happens if you need to open a class that it shouldn't instantiate?  
`class String; end` That's fine to do, but all of a sudden you can't do it  
because your other code is going to find it.

What if your class needs to use a subclass in order to do its job `class  
Outer; class Inner; end; end` Whoops, your code didn't instantiate Outer  
like it was supposed to, it instantiated Inner instead, which it was not  
supposed to, and there is no way to fix it other than go hack on or add  
special rules to the instantiator, which might in turn break its behaviour  
with the other files it reads.

What happens if you need to put the code somewhere else, but it should be  
instantiated by your instantiator?

What happens when your coworker is reading the code going "now how the fuck  
did this class become part of that list?" (in Python terms: explicit is  
better than implicit)

## Problem 2: You need to write a Ruby parser and traverse ASTs to do this  
right ##

What happens if you need to define a class like this `MyClass = Class.new`?  
Will your parser be smart enough to see it?

What about like this `Object.const_set 'MyClass', Class.new`

What about like this `my_class = Class.new` you won't even be able to access  
that class, how will you instantiate it?

What about like this `class \<\< obj; end`

> **···**
>
> On Sat, Oct 1, 2011 at 11:05 AM, Jeroen van Ingen \<jeroeningen@gmail.com\>wrote:
> 
> > @Adam  
> > I'm not talking about inheritance. I just want to get access to all  
> > ruby-classes inside a list of files in a dir and it subdirs.

---

<div class="post-metadata">

### Author: ![Robert\_K1](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/robert_k1/32/1830_2.png) [@Robert\_K1](https://rubytalk.org/u/Robert_K1)
#### Post date: [1 October 2011 19:04 UTC](https://rubytalk.org/t/get-all-classes-from-a-list-of-files/63713/10 "2011-10-01T19:04:56Z")

</div>

[![]( " - YouTube") ](https://www.youtube.com/watch?v=izzKUoxL11E)

🙂

robert

> **···**
>
> On Sat, Oct 1, 2011 at 6:56 PM, Phillip Gawlowski \<cmdjackryan@gmail.com\> wrote:
> 
> > On Sat, Oct 1, 2011 at 6:05 PM, Jeroen van Ingen \<jeroeningen@gmail.com\> wrote:
> > 
> > > Can you explain why eval() is always the badest solution?
> > 
> > eval('system "rm -rf /"') # Where'd my UNIX go?
> 
> --  
> remember.guy do |as, often| as.you\_can - without end  
> [http://blog.rubybestpractices.com/](http://blog.rubybestpractices.com/)

---

<div class="post-metadata">

### Author: ![Phillip\_Gawlowski](https://avatars.discourse-cdn.com/v4/letter/p/ecc23a/32.png) [@Phillip\_Gawlowski](https://rubytalk.org/u/Phillip_Gawlowski)
#### Post date: [1 October 2011 19:24 UTC](https://rubytalk.org/t/get-all-classes-from-a-list-of-files/63713/11 "2011-10-01T19:24:05Z")

</div>

It's a love/hate relationship for me. Mostly hate. 😉

> **···**
>
> On Sat, Oct 1, 2011 at 9:04 PM, Robert Klemme \<shortcutter@googlemail.com\> wrote:
> 
> > [http://www.youtube.com/watch?v=izzKUoxL11E](http://www.youtube.com/watch?v=izzKUoxL11E)
> > 
> > 🙂
> 
> --  
> Phillip Gawlowski
> 
> gplus.to/phgaw | twitter.com/phgaw
> 
> A method of solution is perfect if we can forsee from the start,  
> and even prove, that following that method we shall attain our aim.  
> -- Leibniz
