Get a class by name in Ruby?

后端 未结 4 1103
眼角桃花
眼角桃花 2020-12-02 14:01

Having a string with the module and name of a class, like:

\"Admin::MetaDatasController\"

how do I get the actual class?

The follow

相关标签:
4条回答
  • 2020-12-02 14:41

    If you want something simple that handles just your special case you can write

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

    But if you want something more general, split the string on :: and resolve the names one after the other:

    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")
    

    On the first iteration Object is asked for the constant Admin and returns the Admin module or class, then on the second iteration that module or class is asked for the constant MetaDatasController, and returns that class. Since there are no more components that class is returned from the method (if there had been more components it would have iterated until it found the last).

    0 讨论(0)
  • 2020-12-02 14:48

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

    Object.const_get('Admin::MetaDatasController')
    => Admin::MetaDatasController
    
    0 讨论(0)
  • 2020-12-02 14:58

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

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

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

    0 讨论(0)
  • 2020-12-02 15:02

    i could be way off-base, but wouldn't eval return the class?

    eval("Admin::MetaDatasController")
    

    so eval("Admin::MetaDatasController").new would be the same as Admin::MetaDatasController.new

    0 讨论(0)
提交回复
热议问题