在String和Classname之间转换

时间:2009-09-19 10:30:08

标签: ruby string class constants

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

Article.all

等等。

有什么想法吗?

3 个答案:

答案 0 :(得分:4)

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

# 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

答案 1 :(得分:3)

class Abc
end #=> nil
klass = eval("Abc") #=> Abc
klass.new #=> #<Abc:0x37643e8>

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

在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

答案 2 :(得分:0)

我不确定我是否理解你的意图。在这里,我假设allArticle的类方法,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"]