2010-04-24 20 views

Respuesta

6

Como opción, hay un binding_of_caller gem que le permite ejecutar código en el contexto de cualquier persona que llama en la pila de llamadas (llamante, llamante, etc.). Es útil para inspeccionar (lea haga cualquier cosa en cualquier posición en la pila de llamadas) call stack in development, como se usa en better_errors.

Los objetos de la clase Binding encapsulan el contexto de ejecución en algún lugar particular del código y conservan este contexto para uso futuro.

http://www.ruby-doc.org/core-2.1.4/Binding.html

Debo mencionar, esta técnica sólo se debe utilizar para la depuración, diversión o con fines educativos, porque viola los principios de la programación orientada a objetos muy mal.
Principalmente por eval.

Vamos a preparar cosas:

require 'binding_of_caller' # I assume, you installed this gem already? 

Consigue el (la más cercana en la pila, por lo tanto, 0) instancia de llamada inmediata:

binding.of_caller(0).eval('self') 

...o incluso un método de llamada inmediata:

binding.of_caller(0).eval('__method__') 

Si usted necesita para obtener más arriba en la pila de llamadas, utilizar números distintos de 0 para conseguir de una persona que llama vinculante.

Awfully hacky. Pero si realmente necesitas este —, ahí tienes.

1

¿Quiere decir self?

irb> class Object 
    .. def test 
    ..  self 
    .. end 
    .. end 
    => nil 
irb> o = Object.new 
    => #<Object:0xb76c5b6c> 
irb> o.test 
    => #<Object:0xb76c5b6c> 
+17

++ Amigo, eso es totalmente impresionante la forma en que se ve como un Z estilizado – Pierreten

+0

Leí la pregunta que dentro de su 'test()' OP quiere obtener el objeto que obtienes si escribes 'self' en irb. – lulalala

12

Usted puede buscar fácilmente en la línea de código que llama a la función de interés a través

caller.first 

que le dicen el número de nombre de archivo y línea que llama a la función correspondiente. A continuación, puede volver a calcular qué objeto era.

Sin embargo, parece que estás más detrás de algún objeto que llamó a cierta función, quizás dentro de un método de instancia. No conozco un método para resolver esto, pero no lo usaría de todos modos, ya que parece violar la encapsulación mal.

+1

Ese es un buen punto, pasaré el objeto que llama La idea era simplificar algunos de los argumentos de un método al reflejar automáticamente cierta información sobre el objeto que llama. –

+1

, idealmente, si es más de una vez, debería ser un método en una superclase, y puedes usar 'self '. – Peter

2

Tecnología en su máxima expresión:

1 # phone.rb 
2 class Phone 
3 def caller_id 
4  caller 
5 end 
6 end 
7 
8 class RecklessDriver 
9 def initialize 
10  @phone = Phone.new 
11 end 
12 def dial 
13  @phone.caller_id 
14 end 
15 end 
16 
17 p = Phone.new 
18 p.caller_id.inspect # => ["phone.rb:18:in `<main>'"] 
19 
20 macek = RecklessDriver.new 
22 macek.dial.inspect # => ["phone.rb:13:in `dial'", "phone.rb:22:in `<main>'"] 

Nota: número línea con fines demostrativos.phone.rb:X se refiere a la línea X de la secuencia de comandos.

¡Mire phone.rb:13! ¡Este método dial es lo que envió la llamada! ¡Y phone.rb:22 se refiere al controlador imprudente que utilizó el método dial!

1

Pedro answer utilizado en el ejemplo de código de producción

En mi compañía fueron deprecating deleted bandera en el sabor de Paranoia gemdeleted_at columna. El abajo código es cómo nos aseguramos de que todo irá bien antes de extraer la columna (la implementación de este código y luego después de 2 ó 3 días de estar vivo desplegamos la migración remoove_column :lessons, :deleted

class Lesson < ActiveRecord::Base 

    def deleted 
    if caller.select { |c| c.match /serialization\.rb/ }.any? 
     # this is Rails object mapping 
     !!deleted_at 
    else 
     raise 'deplicated - deleted was replaced by deleted_at' 
    end 
    end 
end 
Cuestiones relacionadas