2010-08-12 119 views
62

如何从包含该类名的字符串中调用类? (我想我可以做case /但是看起来很难看)ruby​​将字符串中的类名转换为实际类

我问的原因是因为我使用acts_as_commentable插件等等,并且它们将commentable_type存储为列。我希望能够调用任何特殊的可评论课程来对其做一个find(commentable_id)

谢谢。

回答

90

我想你想要的是constantize

这是一个RoR结构。我不知道如果有一对红宝石核心

+0

完美,这正是我一直在寻找。 – unsorted 2010-08-12 01:12:54

+33

对于普通的Ruby,你可以使用'Module.const_get'。 'constantize'的优点在于它可以在深层嵌套的命名空间下工作,因此您可以执行'Functional :: Collections :: LazyList'.constantize'并从模块Functional中的模块集合中获取LazyList类,而使用' const_get',你必须做一些像'Functional :: Collections :: LazyList'.split('::')。reduce(Module,:const_get)''。 – Chuck 2010-08-12 01:43:48

32
"Object".constantize # => Object 
+1

+1,因为它是同时的 – unsorted 2010-08-12 01:13:19

25

给定一个字符串,第一个电话classify创建一个类名(仍然是一个字符串),然后调用constantize,试图找到并返回类名常数(注意class names are constants)。

some_string.classify.constantize 
+6

你应该使用camelize而不是分类,因为classify是用于表名,并且不能很好地处理复数。 – 2012-07-15 16:14:41

+1

谢谢!那很棒! – duykhoa 2013-03-26 09:15:55

+2

你的答案真的很有价值,但是你应该使用“titleize”作为包含空格的表名,并且从字符串中删除空格来表示完整的类名。 – SSR 2015-04-15 10:05:02

3

如果你想字符串转换为实际工作的类名来访问模型或任何其他类

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` 
3

当的ActiveSupport是可用的(例如,在Rails的):String#constantizeString#safe_constantize,那就是"ClassName".constantize

在纯Ruby中:Module#const_get,通常为Object.const_get("ClassName")

在最近的红宝石中,两者都使用嵌套在模块中的常量,如Object.const_get("Outer::Inner")

7

我知道这是一个古老的问题,但我只是想离开这个笔记,它可能对别人有帮助。

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