Get all classes from a list of files

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

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

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

···

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/\.

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

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

@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/.

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
  Module.nesting.select {|m| m.is_a? Class}
end

Hope this helps,

-Luke

···

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

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

···

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

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

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.

:slight_smile:

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/

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

···

On Sat, Oct 1, 2011 at 9:04 PM, Robert Klemme <shortcutter@googlemail.com> wrote:

http://www.youtube.com/watch?v=izzKUoxL11E

:slight_smile:

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