Get a class by name in Ruby?

The presence of a string with the module and class name, for example:

"Admin::MetaDatasController" 

How to get the actual class?

The following code works if there is no module:

 Kernel.const_get("MetaDatasController") 

but it breaks with the module:

 ruby-1.8.7-p174 > Kernel.const_get("Admin::MetaDatasController") NameError: wrong constant name Admin::MetaDatasController from (irb):34:in `const_get' from (irb):34 ruby-1.8.7-p174 > 
+46
ruby
Jul 02 '10 at 6:26
source share
4 answers

If you need something simple that only handles your special case, you can write

 Object.const_get("Admin").const_get("MetaDatasController") 

But if you want something more general, split the line into :: and resolve the names one by one:

 def class_from_string(str) str.split('::').inject(Object) do |mod, class_name| mod.const_get(class_name) end end the_class = class_from_string("Admin::MetaDatasController") 

At the first iteration of Object the Admin constant is requested and returns the module or Admin class, and then at the second iteration, the MetaDatasController constant is set to this module or class and returns this class, since there are no more components returned by the class from the method (if there were more components, they would be repeated until they find the latter).

+89
Jul 02 '10 at 6:38
source share
— -

ActiveSupport provides a method called constantize that will do this. If you are in Rails, which I assume is based on the name of your constant, then you already have ActiveSupport.

 require 'active_support/core_ext/string' class Admin class MetaDatasController end end "Admin::MetaDatasController".constantize # => Admin::MetaDatasController 

To find out how this method is implemented, open https://github.com/rails/rails/blob/85c2141fe3d7edb636a0b5e1d203f05c70db39dc/activesupport/lib/active_support/inflector/methods.rb#L230-L253

+41
Jul 02 '10 at 7:18
source share

In Ruby 2.x, you can simply do this:

 Object.const_get('Admin::MetaDatasController') => Admin::MetaDatasController 
+18
Jun 26 '14 at 0:29
source share

I could be outside the base, but could not return the class?

 eval("Admin::MetaDatasController") 

therefore, eval("Admin::MetaDatasController").new will be the same as Admin::MetaDatasController.new

+1
Jul 02 2018-10-02T00:
source share



All Articles