在String和Classname之间转换

我有一个包含类名的字符串。 例如,它是包含“Article”的字符串。 该字符串来自params []。 我该怎么做才能使用这个字符串,好像它是一个类名? 例如,我想做:

Article.all 

等等。

任何的想法?

此解决方案优于eval,因为您正在评估可能由用户操纵并可能包含有害操作的params散列。 作为一般规则: 永远不要直接评估用户输入,这是一个很大的安全漏洞。

 # Monkey patch for String class class String def to_class klass = Kernel.const_get(self) klass.is_a?(Class) ? klass : nil rescue NameError nil end end # Examples "Fixnum".to_class #=> Fixnum "Something".to_class #=> nil 

更新 – 适用于命名空间的更好版本:

  # Monkey patch for String class class String def to_class chain = self.split "::" klass = Kernel chain.each do |klass_string| klass = klass.const_get klass_string end klass.is_a?(Class) ? klass : nil rescue NameError nil end end 
 class Abc end #=> nil klass = eval("Abc") #=> Abc klass.new #=> # 

假设确实有一个提供名称的课程……

在ActiveSupport中,有一些String#constantize ,它做了同样的事情,但我相信它在2.1之后已被弃用。

编辑:这是从ActiveSupport 2.1.2实现constantize:

  def constantize(camel_cased_word) names = camel_cased_word.split('::') names.shift if names.empty? || names.first.empty? constant = Object names.each do |name| constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name) end constant end 

我不确定我是否理解你的意图。 在这里,我假设all都是文章的类方法,并返回一系列文章。

 class Article def self.all ["Peopleware" , "The Mythical Man-Month"] end end s = "Article" all_of_article = [] eval("all_of_article = #{s + ".all"}") puts all_of_article.inspect # ["Peopleware", "The Mythical Man-Month"]