在Ruby中按名称获取课程?

pup*_*eno 49 ruby

有一个包含模块和类名的字符串,例如:

"Admin::MetaDatasController"
Run Code Online (Sandbox Code Playgroud)

我如何获得实际课程?

如果没有模块,以下代码可以工作:

Kernel.const_get("MetaDatasController")
Run Code Online (Sandbox Code Playgroud)

但它打破了模块:

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 > 
Run Code Online (Sandbox Code Playgroud)

The*_*heo 90

如果你想要一些简单的东西来处理你的特殊情况你可以写

Object.const_get("Admin").const_get("MetaDatasController")
Run Code Online (Sandbox Code Playgroud)

但是如果你想要更通用的东西,拆分字符串::并一个接一个地解析名字:

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")
Run Code Online (Sandbox Code Playgroud)

在第一次迭代时Object,要求输入常量Admin并返回Admin模块或类,然后在第二次迭代中询问模块或类的常量MetaDatasController,并返回该类.由于没有更多的组件从该方法返回类(如果有更多的组件,它将迭代,直到找到最后一个).

  • 出于兴趣,你为什么使用`Kernel`作为接收器?在`Object`上定义的顶级常量不在`Kernel`上. (2认同)

Jos*_*eek 45

ActiveSupport提供了一个名为constantize的方法,它将执行此操作.如果您使用的是Rails,我认为您基于常量的名称,那么您已经加载了ActiveSupport.

require 'active_support/core_ext/string'

class Admin
  class MetaDatasController
  end
end

"Admin::MetaDatasController".constantize # => Admin::MetaDatasController
Run Code Online (Sandbox Code Playgroud)

要了解该方法的实现方式,请查看https://github.com/rails/rails/blob/85c2141fe3d7edb636a0b5e1d203f05c70db39dc/activesupport/lib/active_support/inflector/methods.rb#L230-L253

  • 添加指向github文件的链接时,按y可获得指向该特定提交的直接链接. (2认同)

hol*_*eap 22

在Ruby 2.x中,您可以这样做:

Object.const_get('Admin::MetaDatasController')
=> Admin::MetaDatasController
Run Code Online (Sandbox Code Playgroud)

  • 请注意,如果您不知道常量是否存在,则可以使用Object.const_get(str)抢救nil或Object.const_defined?(str)&& Object.const_get(str)来实现。 (2认同)