Ruby中是否有一种方法可以使用符号或字符串并将其转换为同名的类?
例如,如果我有一个类,如
class Bob
def talk
puts "Hi, I'm bob"
end
end
我在代码中的其他地方的方法传递了一个符号:bob,我能以某种方式将其转换为类Bob吗?也许像是
b = :Bob.new
b.talk
或者有没有办法做类似的事情?
答案 0 :(得分:53)
有很多方法可以做到这一点。缺乏背景使得无法选择“最佳”方式。这里有几个。
Kernel.const_get(:Bob)
eval(:Bob.to_s)
Kernel.const_get(:bob.to_s.capitalize)
答案 1 :(得分:40)
仅用于Rails。
使用字符串:
"Module".constantize #=> Module
"Class".constantize #=> Class
带有符号:
:module.to_s.classify.constantize #=> Module
:open_struct.to_s.classify.constantize #=> OpenStruct
如果您正在处理多字符号,那么您需要将#classify
添加到链中以正确处理常量的所有部分的大写。< / p>
http://api.rubyonrails.org/classes/ActiveSupport/Inflector.html#method-i-constantize
答案 2 :(得分:10)
如果你想转向,我见过的解决方案都没有工作:foo_bar进入FooBar。如果这就是你要找的东西:
:foo_bar.to_s.split( “_”)收集(安培;:大写)。.join.constantize
=&GT; FooBar
希望能有所帮助。
答案 3 :(得分:5)
NameSpace.const_get(classname)
将返回类对象(假设classname包含类的名称 - 如果它包含不是类的常量的名称,它将返回该常量的值)。顶级命名空间是Object,因此您可以执行Object.const_get(:Bob).new
答案 4 :(得分:3)
class Bob
end
def create(name)
return eval("#{name}.new")
end
b = create(:Bob)
puts b.class
答案 5 :(得分:2)
这是我在寻找包含模块/名称空间支持的类似内容时提出的:
['foo', 'bar'].inject {|r,e| "#{r.classify}::#{e.classify}"}.constantize
可生产
=> Foo::Bar
然而,这需要Rails,当然它只适用于数组有多个元素的地方。
这看起来相当简单,所以我肯定我错过了一些东西,有人会关心为什么这不是一个好方法吗?
谢谢!
答案 6 :(得分:0)
在我的情况下,下面的示例都有效,但您也不必忘记命名空间:
Object.const_get("ModuleName::#{class_model_name}")
或
Kernel.const_get("ModuleName::#{class_model_name}").