2010-05-26 9 views
37

Esto es cómo convertir una cadena a una clase de rieles/Ruby:¿Cómo convierto una cadena en un método de clase?

p = "Post" 
Kernel.const_get(p) 
eval(p) 
p.constantize 

Pero lo que si estoy Recuperación de un método de una matriz/activa registro de objeto como:

Post.description 

pero podría ser

Post.anything 

donde anything es una cadena como anything = "description".

Esto es útil ya que quiero refactorizar una clase muy grande y reducir las líneas de código y la repetición. ¿Cómo puedo hacer que funcione?

+0

se da cuenta de que sólo necesita uno de {const_get, eval, constantize}, a la derecha ? – klochner

+0

sí. Por supuesto que sí. como acabo de probar el 3. – kgpdeveloper

Respuesta

61
Post.send(anything) 
+0

funcionando perfectamente, gracias. reducido tantas líneas de código a solo unas pocas. – kgpdeveloper

+0

Para que pueda aceptar la respuesta. – shingara

+0

si mi método es como: def test = (string) {puts string}. No creo que Post.send ("prueba", "hola") funcione bien. –

15

Mientras eval puede ser una herramienta útil para este tipo de cosas, y los de otros orígenes pueden tomar para usarlo tan a menudo como era de un abridor de latas, en realidad es peligroso utilizar tan a la ligera. Eval implica que cualquier cosa puede suceder si no tienes cuidado.

Un método más seguro es la siguiente:

on_class = "Post" 
on_class.constantize.send("method_name") 
on_class.constantize.send("method_name", arg1) 

Objeto # Enviar llamará el método que desee. Puede enviar un Símbolo o una Cadena y, siempre que el método no sea privado o esté protegido, debería funcionar.

+0

Esto ya está ejecutando métodos arbitrarios. La seguridad no parece ser un factor importante aquí. – Chuck

+0

Los métodos arbitrarios son muy diferentes del código arbitrario. Dudo que tengas un método de "DEJAR TODAS LAS TABLAS" en tu clase. También es fundamental verificar que una cadena dada es segura o no para usar como nombre de método, puede tener una lista blanca simple para verificar, sin embargo, es imposible evaluar el peligro de un bloqueo evaliario arbitrario. – tadman

0

Prueba esto:

class Test 
def method_missing(id, *args) 
    puts "#{id} - get your method name" 
    puts "#{args} - get values" 
end 
end 

a = Test.new 
a.name('123') 

Así que la sintaxis general habría a.<anything>(<any argument>).

12

Dado que se trata como una cuestión de Ruby on Rails, elaboraré un poco.

En Rails 3, asumiendo title es el nombre de un campo en un objeto ActiveRecord, a continuación, el siguiente también es válido:

@post = Post.new 
method = "title" 

@post.send(method)    # => @post.title 
@post.send(method+'=',"New Name") # => @post.title = "New Name" 
Cuestiones relacionadas