12

Assuming I can construct a string that matches an existing class, how do I invoke it?

For example, I have several classes:

  • MyClass1
  • MyClass2
  • MyClass3

And I want to dynamically invoke each of them by constructing a string that matches their names. If they all had the method "methods", how do I do something like this?:

(1..3).each do |n|
  ("MyClass"+n).methods
end
comb
  • 185
  • 2
  • 9
  • Are you sure anonymous classes in an array wouldn't fit? As soon as you start using the namespace by iteration, you should rethink your code. – Reactormonk Jul 15 '12 at 11:57
  • Hi Tass, can you expand on "anonymous classes in an array"? I'm fairly positive this isn't the best way to solve a problem I'm currently working on, but I thought I should know how to do something like this anyway. – comb Jul 15 '12 at 17:47

2 Answers2

20

constantize fits the bill. You can read more about it here. In your case it would be something like:

(1..3).each do |n|
  "MyClass#{n}".constantize.methods
end
zsquare
  • 9,916
  • 6
  • 53
  • 87
  • Thank you! Following up on zsquare's answer, I ended up with two answers! klass = Object.const_get "MyClassName" -or- klass = "MyClassName".constantize Both return the class for whatever brand of fun you're interested in. While looking around, I also found the Inflector class to be handy for dynamically building class names. http://api.rubyonrails.org/classes/ActiveSupport/Inflector.html#method-i-camelize – comb Jul 15 '12 at 07:59
-3

you can also do -

(1..3).each {|n| eval "MyClass#{n}.methods"}
saihgala
  • 5,724
  • 3
  • 34
  • 31
  • 1
    Downvote for `eval`. You shouldnt use something like `eval` unless you are sure you have to, and are sure there is NO other way to do it. And then, if you're sure you are probably doing something wrong. – zsquare Jul 15 '12 at 08:27
  • if you need to do it in ruby i.e. no rails, what other way would you invoke it? – saihgala Jul 15 '12 at 08:54
  • 1
    `classname = 'Integer'; Kernel.const_get(classname).methods` – zsquare Jul 15 '12 at 09:04