2010-01-10 10 views
12

Estoy tratando de encontrar la manera de crear dinámicamente métodosRubí método class_eval

class MyClass 
    def initialize(dynamic_methods) 
    @arr = Array.new(dynamic_methods) 
    @arr.each { |m| 
     self.class.class_eval do 
     def m(*value) 
      puts value 
     end 
     end 
    } 
    end 
end 

tmp = MyClass.new ['method1', 'method2', 'method3'] 

Desafortunadamente esto sólo crea el método m, pero tengo que crear métodos basados ​​en el valor de m, ideas?

Respuesta

27

Hay dos formas aceptadas:

  1. Use define_method:

    @arr.each do |method| 
        self.class.class_eval do 
        define_method method do |*arguments| 
         puts arguments 
        end 
        end 
    end 
    
  2. Uso class_eval con un argumento de cadena:

    @arr.each do |method| 
        self.class.class_eval <<-EVAL 
        def #{method}(*arguments) 
         puts arguments 
        end 
        EVAL 
    end 
    

La primera opción convierte un cierre en un método, la segunda opción evalúa una cadena (heredoc) y utiliza el enlace de método regular. La segunda opción tiene una ventaja de rendimiento muy leve al invocar los métodos. La primera opción es (posiblemente) un poco más legible.

+0

Gracias, exactamente lo que necesitaba. – Bob

+0

Es posible que desee tener en cuenta que debe tener más cuidado sobre el segundo método, por ejemplo, evitar el código como https://github.com/rails/rails/blob/f1d8f2af72e21d41efd02488f1c2dcf829e17783/actionpack/lib/action_dispatch/routing/route_set.rb#L188-200 –

4
define_method(m) do |*values| 
    puts value 
end 
+0

Genial, eso funciona, pero ¿cómo especifico el valor como un parámetro opcional? – Bob

+0

Oh, solo agrega un "*" como ese? define_method (m) do | * value | – Bob

+1

Derecha (Acabo de editarlo para ese efecto). Sin embargo, tenga en cuenta que '* value' no significa que" value es un argumento opcional ". Significa que "valor es una matriz que contiene todos los argumentos (de los cuales podría haber un número arbitrario). – sepp2k

Cuestiones relacionadas