I’m been doing some work in Ruby to build a parser framework and I wanted to have pluggable parsers from the command line. I figured this would be simple because in Java it actually is pretty simple, as long as the pluggable parser is in the classpath. Well, with Ruby, this isn’t quite the case. Even if a class is in the load path, it still isn’t visible until it has been loaded either via the load method or the require method on Kernel. This is annoying and something I wasn’t used to. But a quick hackery fixes this nicely:
# Load all the local rb files Dir.glob("*.rb").each do |d| load(d) unless d == $0 end
This loads every *.rb file in the current directory into the current Ruby process. Then you can do some String reflection magic to load a class:
parser = eval(ARGV + "Parser.new(ARGV.downcase())")
This allows me to call my scriptage and pass in the prefix of the class name like this:
ruby scriptage.rb MySpecial
This will then instantiate an instance of MySpecialParser. I could have iterated over all the constants in the entire Ruby process and found the symbol I needed and then called new on that, but that sucks. Eval is much cleaner in this case.
In fact, in Java loading a class by name is simple:
Class.forName("com.inversoft." + prefix + "Parser");
In Ruby this doesn’t work so well. You have to first load all the .rb files like I did and then use eval. They really should add something to Class or ObjectSpace or Kernel to do all this for you. In fact, I think in 2.0 load_path should be able to load all files in the load path via reflection without any requires or load crapola.
2 thoughts on “Ruby reflection 'requires' a lot”
Have you tried this:
That said, a String.to_class method would be nice.
Im not sure if i understand… but do you want to do this?
$evClass = eval(“MyClass”).new
Hope that it helps