Creating objects without knowing their names

Hi

I'd like to load an arbitary number of Ruby files from a directory and
create their associated objects. However, I don't know the class names
of the files that have just been loaded. Is it possible to determine a
file's class name once that file has been loaded? (Without resorting to
parsing, or enforcing a mapping between the filename and class name.)

What I want to do is something like the following:

    converter_names = Array.new
    Find.find("./converters") do |filename|
      converter_names.push(filename) if filename =~ /rb$/
    end

    converters = Array.new
    converter_names.each do |converter_name|
      load converter_name
      klassName = ...?
      converters.push(Object.const_get(klassName).new)
    end

Many thanks

Paul

You probably know this already, but for the benefit of bystanders: there
isn't in general one-to-one mapping between classes and files. A class
can be defined across several files; a file can contain several class
definitions. (Maybe in the case of the files you are using there is
always a 1-1 map, though.)

I like to use module_eval to solve this problem by reading the file and
evaling its definitions in the context of a new module. It's all wrapped
up neatly in my "script" library on RAA.

For example:

$ cat cl.rb
class MyWeirdClass
  def foo
  end
end

SOME_CONSTANT = 3

$ cat script-ex.rb
require 'script'

script = Script.load "cl.rb"

p script
p script.constants
script_objects = script.constants.map {|k| script.const_get(k)}
script_classes = script_objects.grep(Class)
p script_classes

$ ruby script-ex.rb
#<Script:/home/vjoel/ruby/misc/cl.rb>
["SOME_CONSTANT", "MyWeirdClass"]
[#<Script:0xb7d794a4>::MyWeirdClass]

This also has the benefit of keeping every name from the external file
in a new module's namespace. The return value of Script.load is that module.

···

paul.p.carey@gmail.com wrote:

Hi

I'd like to load an arbitary number of Ruby files from a directory and
create their associated objects. However, I don't know the class names
of the files that have just been loaded. Is it possible to determine a
file's class name once that file has been loaded? (Without resorting to
parsing, or enforcing a mapping between the filename and class name.)

What I want to do is something like the following:

    converter_names = Array.new
    Find.find("./converters") do |filename|
      converter_names.push(filename) if filename =~ /rb$/
    end

    converters = Array.new
    converter_names.each do |converter_name|
      load converter_name
      klassName = ...?
      converters.push(Object.const_get(klassName).new)
    end

--
      vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Joel VanderWerf wrote:

Hi

I'd like to load an arbitary number of Ruby files from a directory
and create their associated objects. However, I don't know the class
names of the files that have just been loaded. Is it possible to
determine a file's class name once that file has been loaded?
(Without resorting to parsing, or enforcing a mapping between the
filename and class name.)

You probably know this already, but for the benefit of bystanders:
there isn't in general one-to-one mapping between classes and files.
A class
can be defined across several files; a file can contain several class
definitions. (Maybe in the case of the files you are using there is
always a 1-1 map, though.)

There are other options. Some of them:

- Make sure all classes on those files inherit a base class which
overrides #inherited so it gets notified every time a sub class is
created. You can then store the set of sub classes in a member of the
base class and use that for whatever purposes.

- Make classes in those files register with some arbitrary registry you
create (that's basically the same as the first just more explicit).

- use set_trace_func to trance execution of those files and notice
whenever a new class occurs. (Not sure whether that works though).

Kind regards

    robert

···

paul.p.carey@gmail.com wrote:

Robert Klemme wrote:

Joel VanderWerf wrote:
>> Hi
>>
>> I'd like to load an arbitary number of Ruby files from a directory
>> and create their associated objects. However, I don't know the class
>> names of the files that have just been loaded. Is it possible to
>> determine a file's class name once that file has been loaded?
>> (Without resorting to parsing, or enforcing a mapping between the
>> filename and class name.)

> You probably know this already, but for the benefit of bystanders:
> there isn't in general one-to-one mapping between classes and files.
> A class
> can be defined across several files; a file can contain several class
> definitions. (Maybe in the case of the files you are using there is
> always a 1-1 map, though.)

There are other options. Some of them:

- Make sure all classes on those files inherit a base class which
overrides #inherited so it gets notified every time a sub class is
created. You can then store the set of sub classes in a member of the
base class and use that for whatever purposes.

- Make classes in those files register with some arbitrary registry you
create (that's basically the same as the first just more explicit).

- use set_trace_func to trance execution of those files and notice
whenever a new class occurs. (Not sure whether that works though).

Kind regards

    robert

Or you can compare the classes you had before loading to classes you
had after loading. Something like this:

def defined_classes
    classes =
    ObjectSpace.each_object(Class){|c| classes << c}
    classes
end

initial_classes = defined_classes
require 'net/http'
p defined_classes - initial_classes

···

> paul.p.carey@gmail.com wrote:

All very helpful answers. Many thanks indeed.
Paul

m4rkusha@gmail.com wrote:

Or you can compare the classes you had before loading to classes you
had after loading. Something like this:

def defined_classes
    classes =
    ObjectSpace.each_object(Class){|c| classes << c}
    classes
end

initial_classes = defined_classes
require 'net/http'
p defined_classes - initial_classes

Unreliable if your "script" files also require libraries. You still have
to pick out the classes you are looking for.

···

--
      vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407