ruby将字符串中的类名称转换为实际类


87

如何从其中包含该类名称的字符串中调用一个类?(我想我可以做案件,但那看起来很丑。)

我问的原因是因为我正在使用acts_as_commentable插件等,这些插件将commentable_type存储为一列。我希望能够调用任何特定的可注释类来对此进行find(commentable_id)处理。

谢谢。

Answers:


131

我想你想要的是 constantize

这是一个RoR构造。我不知道有没有红宝石核


完美,这正是我想要的。
未分类

40
对于纯Ruby,您可以使用Module.const_get。这样做的好处constantize是,即使在深度嵌套的名称空间中也可以使用它,因此您可以'Functional::Collections::LazyList'.constantize从Functional模块中的Collections模块中获取类LazyList,而对于const_get,您必须执行'Functional::Collections::LazyList'.split('::').reduce(Module, :const_get)
查克(Chuck)2010年

45
"Object".constantize # => Object

请注意,这.constantize是一种Rails方法,您不会在普通的Ruby中找到它
Edgar Ortega

34

给定一个字符串,首先调用classify创建一个类名(仍然是一个字符串),然后调用constantize尝试查找并返回该类名常量(请注意,类名是constant)。

some_string.classify.constantize

10
您应该使用camelize而不是classify,因为classify是用于表名的,并且不能很好地处理复数。
彼得·布朗

1
谢谢!那很棒!
duykhoa

2
您的答案确实很有价值,但是您应该对表名使用“ titleize”(包括空格),并从字符串中删除空格以表示完整的类名。
SSR 2015年

22

我知道这是一个老问题,但是我只想留下这条笔记,这可能对其他人有帮助。

在普通的Ruby中,Module.const_get可以找到嵌套常量。例如,具有以下结构:

module MyModule
  module MySubmodule
    class MyModel
    end
  end
end

您可以按以下方式使用它:

Module.const_get("MyModule::MySubmodule::MyModel")
MyModule.const_get("MySubmodule")
MyModule::MySubmodule.const_get("MyModel")


6

如果要将字符串转换为实际的类名称以访问模型或任何其他类

str = "group class"

> str.camelize.constantize 'or'
> str.classify.constantize 'or'
> str.titleize.constantize

Example :
  def call_me(str)
    str.titleize.gsub(" ","").constantize.all
  end

Call method : call_me("group class")

Result:
  GroupClass Load (0.7ms) SELECT `group_classes`.* FROM `group_classes`
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.