Reputation: 15129
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 string as if it was a class name? For instance, I want to do:
Article.all
and so on.
Any idea?
Upvotes: 1
Views: 1522
Reputation: 24010
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
Upvotes: 4
Reputation: 52326
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
Upvotes: 3
Reputation: 40761
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"]
Upvotes: 0