Como invocar as classes dinamicamente sem usar eval?
Pergunta
É possível se livrar do eval declaração abaixo? O código abaixo filtros para fora todas as classes que são derivados de ClasseBase tipo. Posteriormente essas classes são instanciado e método de 'Olá' é chamado.
module MySpace
class BaseClass
def hello; print "\nhello world"; end
end
class A<BaseClass
def hello; super; print ", class A was here"; end
end
class B<BaseClass
def hello; super; print ", I'm just a noisy class"; end
end
MySpace.constants.each do | e |
c=eval(e)
if c < BaseClass
c.new.hello
end
end
end
Assim, após a execução a saída é:
Olá mundo, Eu sou apenas uma classe
barulhento
Olá mundo, classe A foi aqui
Eu acho que o uso desnecessário de eval é mau. E eu não tenho certeza se o uso de eval é obrigatório aqui. É que há uma maneira mais inteligente em invocar todas as classes de tipo "ClasseBase" dinamicamente?
Solução
c = MySpace.const_get(e)
Outras dicas
eval é a única maneira que eu conheço para transformar uma string em uma constante. É ainda a maneira trilhos faz isso: http://api.rubyonrails.com/classes/Inflector.html#M001638
O curioso é que as constantes retorna strings.
Você já olhou para class_eval
vez?
------------------------------------------------------ Module#class_eval mod.class_eval(string [, filename [, lineno]]) => obj mod.module_eval {|| block } => obj ------------------------------------------------------------------------ Evaluates the string or block in the context of _mod_. This can be used to add methods to a class. +module_eval+ returns the result of evaluating its argument. The optional _filename_ and _lineno_ parameters set the text for error messages. class Thing end a = %q{def hello() "Hello there!" end} Thing.module_eval(a) puts Thing.new.hello() Thing.module_eval("invalid code", "dummy", 123) produces: Hello there! dummy:123:in `module_eval': undefined local variable or method `code' for Thing:Class