2012-02-27 16 views
7

instance_eval cambio de método de auto en su bloque, por ejemplo:¿Cómo cambiar auto en un bloque como lo hace el método instance_eval?

class D; end 
d = D.new 
d.instance_eval do 
    puts self # print something like #<D:0x8a6d9f4>, not 'main'! 
end 

Si definimos un método mismos (o cualquier otro método (que no sea instance_eval) que tiene un bloque), cuando la auto impresión, vamos a conseguir 'principal ', que es diferente de method.eg instance_eval:

[1].each do |e| 
    puts self # print 'main' 
end 

¿Cómo puedo definir un método (que tiene un bloque) como instance_eval? Gracias de antemano.

+0

¿Qué hacer que quiere lograr? – megas

+0

No creo que sea posible hacer lo que quieras. Probablemente porque sería demasiado confuso si pudieras cambiarte a ti mismo. –

Respuesta

7

Puede escribir un método que acepta un argumento proc y, a continuación, pasar eso como un argumento proc para instance_eval.

class Foo 
    def bar(&b) 
    # Do something here first. 
    instance_eval &b 
    # Do something else here afterward, call it again, etc. 
    end 
end 

Foo.new.bar {self} pone

Los rendimientos

#<Foo:0x100329f00> 
+0

Entiendo lo que quiere decir, pero no resolvió mi problema. Quiero definir un método como instance_eval en lugar de usar instance_eval. Quiero que la implementación no sea un envoltorio. ¡Gracias de todos modos! – gaols

+1

Deberás ser más específico sobre lo que quieres lograr, entonces. Si simplemente desea un método que pueda aceptar un bloque y luego ejecutarlo una o más veces dentro del mismo contexto que su método, entonces esto lo hace. Si tuviera que adivinar, ¿quizás también quieres pasarle argumentos al bloque? Sé que es posible porque RSpec lo hace, y es verdad que este ejemplo no. Debería echar un vistazo al código RSpec y ver cómo lo hacen. –

+0

En realidad, veo que RSpec no pasa los parámetros para bloquear, y usa instance_eval para llamar a los bloques. Consulte http://rubydoc.info/gems/rspec-core/RSpec/Core/Example#run-instance_method y haga clic en "Ver código fuente". –

3

Es obvio:

class Object 
    def your_method(*args, &block) 
    instance_eval &block 
    end 
end 

receiver = Object.new 

receiver.your_method do 
    puts self #=> it will print the self of receiver 
end 
+0

Lo siento, lo que quiero es un método que toma un bloque y en ese bloque el yo se cambia a receptor, ¡al igual que instancia_eval! – gaols

+0

¡Gracias de nuevo por su ayuda! – gaols

Cuestiones relacionadas