2010-06-23 7 views
13

Estaba leyendo en RSpec y estaba tratando de averiguar cómo se implementó el "debería" de RSpec.Metaprogramación de Ruby, ¿cómo funciona el "debería" RSpec?

¿Podría alguien dar una mano sobre cómo funciona la meta naturaleza de esta función?

El código se encuentra aquí:

http://github.com/dchelimsky/rspec/blob/master/lib/spec/expectations/extensions/kernel.rb

TIA,

-Daniel

Aclaración:

target.should == 5 

¿Cómo el valor de destino van pasando junto a "debe ", que a su vez era" == "'d contra 5?

Respuesta

27

Eche un vistazo a class OperatorMatcher.

Todo se reduce a Ruby, lo que le permite dejar fuera períodos y paréntesis. Lo que en realidad está escribiendo:

target.should.send(:==, 5) 

Es decir, enviar el mensaje should al objeto target, a continuación, enviar el mensaje == a cualquier should devoluciones.

El método should tiene un parche parche en Kernel, por lo que puede ser recibido por cualquier objeto. El Matcher devuelto por should tiene el actual que en este caso es target.

El Matcher implementa el método == el que hace la comparación con el expected que, en este caso, es el número 5. Un cortado ejemplo, que puede intentar usted mismo:

module Kernel 
    def should 
    Matcher.new(self) 
    end 
end 

class Matcher 
    def initialize(actual) 
    @actual = actual 
    end 

    def == expected 
    if @actual == expected 
     puts "Hurrah!" 
    else 
     puts "Booo!" 
    end 
    end 
end 

target = 4 
target.should == 5 
=> Booo! 

target = 5 
target.should == 5 
=> Hurrah! 
+3

Gracias fo un pequeño gran explicación eso no solo responde la pregunta sino que es un buen resumen de algunos mecanismos en Ruby. Para las personas nuevas en Ruby, tenga en cuenta que la última expresión en una función es implícitamente el valor de retorno, por lo que debería ser superior en C++ Matcher * Kernel :: should() { return new Matcher (this); } –

+0

@Andy Dent: gracias por el comentario positivo –

+2

Primero: Muy buena respuesta, muchas gracias! Dos observaciones rápidas: en lugar de definir "debería" en el módulo Kernel, podría hacerlo en la clase Object. Lo encuentro más seguro, ya que es menos genérico. Lo segundo es que no necesitas metaprogramación para definir el método ==. Simplemente puede definirlo como cualquier otro método normal, para que sea más fácil de leer: def == (expected) –

Cuestiones relacionadas