tags:

views:

88

answers:

3

Hello,

Let's say I have a class named Klass, and a class called Klass2. Depending on the user's input, I'd like to decide whether I'll call "hello_world" on Klass, or Klass2:

class Klass
  def self.hello_world
    "Hello World from Klass1!"
  end
end

class Klass2
  def self.hello_world
    "Hello World from Klass2!"
  end
end

input = gets.strip
class_to_use = input
puts class_to_use.send :hello_world

The user inputs "Klass2" and the script should say:

Hello World from Klass2!

Obviously this code doesn't work, since I'm calling #hello_world on String, but I'd like to call #hello_world on Klass2.

How do I "convert" the string into a referrence to Klass2 (or whatever the user might input), or how could I else would I achieve this behavior?

+8  A: 
puts Object.const_get(class_to_use).hello_world
Jörg W Mittag
Is it better to use `Object.const_get`? I've never used it... tks! :]
j.
+1  A: 
puts eval(class_to_use).hello_world
j.
`eval` is always a bit unsafe and can be avoided by `const_get`. Also, there's no need for using `send`, as we already know that we will call `hello_world` method.
Mladen Jablanović
why is it unsafe? and I removed the `send`... totally missed that. thank you.
j.
@j: `eval` lets the user run any arbitrary Ruby code. They could do much more than pick a class.
Benjamin Oakes
Right, sooner or later you'll have a user which will like to hear how class by the name of `system('rm -rf /')` says "hello" to the world... ;)
Mladen Jablanović
Right. Got it. Thank you both!
j.
@j: Happy to help. I always look for other options before resorting to `eval`. (Ruby has a lot of dynamic programming methods available, for instance.)
Benjamin Oakes
Not only is `eval` insecure, but it's incredibly slow on every Ruby implementation I know of. I don't want to encourage premature optimization, but it's so easy to avoid `eval` in most cases that it's really just wasteful.
Chuck
+1  A: 

If you have ActiveSupport loaded (e.g. in a Rails app) you can also use #constantize:

class_to_use.constantize.hello_world
severin