Cast between String and Classname

前端 未结 3 1954
孤街浪徒
孤街浪徒 2020-12-20 07:39

I have a string, containing an Class name. It is, for example, a string containing \"Article\". That string came up from the params[]. What should I do to work with this str

相关标签:
3条回答
  • 2020-12-20 08:19

    This solution is better than eval as you are evaluating params hash that might be manipulated by the user and could contain harmful actions. As a general rule: Never evaluate user input directly, that's a big security hole.

    # 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
    

    Update - a better version that works with namespaces:

     # 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
    
    0 讨论(0)
  • 2020-12-20 08:22

    I am not sure whether I understand your intention correctly. Here I assume all is an Class method of Article and all return an array of articles.

    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"]
    
    0 讨论(0)
  • 2020-12-20 08:36
    class Abc
    end #=> nil
    klass = eval("Abc") #=> Abc
    klass.new #=> #<Abc:0x37643e8>
    

    Assumes there really is a class with the name provided...

    In ActiveSupport, there was String#constantize, which did the same thing, but I believe it's deprecated after 2.1.

    EDIT: this is the implementation of constantize from ActiveSupport 2.1.2:

      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
    
    0 讨论(0)
提交回复
热议问题