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