From: "Ara.T.Howard" Date: 2004-07-26T22:41:54+09:00 Subject: Re: code introspection On Mon, 26 Jul 2004, Daniel Cremer wrote: > Hi, > > Is there a solution to do code introspection rather than introspection > at the level of the Module/Object ? I can't figure out if I'm looking > for something that isn't there in Ruby since I've been reading C# code > or if I'm missing something. Let me explain my problem. > I would like to load ruby source files and dynamically create objects > from classes located inside these sources. It's one class/object per > source file and I can make it so that a string from a configuration > file holds the name of the class. However I can't figure out a good > way to use that string to get to the class in the source file. > > I could use eval but am really uncomfortable with that for obvious > reasons (people keep saying it's evil so I don't play with him). The > other solution I came up with was to add a method in the same source > but outside the class to return the desired object: > > --------------source file--------- > class MyNewClass > ... > end > > def create_loaded_class() > return MyNewClass.new() > end > --------------------------------- > > Then as I require the source files I can successively invoke the > create_loaded_class method. This works but can get quite messy as > there are a lot of things to consider if you need to reload sources > and create new objects etc. > Please tell me I'm missing something obvious :). > > thanks, > Daniel ~ > cat c.rb files = %w(a.rb b.rb) files.each do |file| load file name, klass = Common.introspect file p name p klass klass.new end ~ > ruby c.rb "Foo" Common::Foo "foo" "Bar" Common::Bar "bar" ~ > cat a.rb module Common class Foo def initialize p 'foo' end end class << self def introspect path @introspect[File.basename(path)] end end @introspect = {} unless defined? @introspect @introspect[File.basename(__FILE__)] = 'Foo', Foo end ~ > cat b.rb module Common class Bar def initialize p 'bar' end end class << self def introspect path @introspect[File.basename(path)] end end @introspect = {} unless defined? @introspect @introspect[File.basename(__FILE__)] = 'Bar', Bar end you could obviously do this without the 'Common' module - but i think it's cleaner/safer this way - provided you can manage to wrap all your modules this way... kind regards. -a -- =============================================================================== | EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov | PHONE :: 303.497.6469 | A flower falls, even though we love it; | and a weed grows, even though we do not love it. | --Dogen ===============================================================================