programas - programacion con objetos ruby
¿Alguna forma de determinar qué objeto llama un método? (5)
¿Quieres decir como self
?
irb> class Object
.. def test
.. self
.. end
.. end
=> nil
irb> o = Object.new
=> #<Object:0xb76c5b6c>
irb> o.test
=> #<Object:0xb76c5b6c>
Espero que la infraestructura de transmisión de mensajes de Ruby signifique que podría haber algún truco inteligente para esto.
¿Cómo puedo determinar el objeto que llama? ¿Qué objeto se llama el método en el que estoy actualmente?
La answer de Pedro utilizada en el ejemplo de código de producción.
En mi compañía, estábamos desaprobando la bandera deleted
en el sabor de la columna deleted
de Paranoia gema . El siguiente código es cómo nos aseguramos de que todo saldrá bien antes de eliminar la columna (implementando este código y luego de 2 o 3 días de estar remoove_column :lessons, :deleted
implementamos 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
Puede mirar fácilmente la línea de código que llamó la función de interés a través de
caller.first
que le indicará el nombre del archivo y el número de línea que llamó a la función relevante. A continuación, podría volver a calcular qué objeto era.
Sin embargo, parece que estás más cerca de un objeto que llama una función determinada, tal vez dentro de un método de instancia. No tengo conocimiento de un método para resolver esto, pero no lo usaría de todos modos, ya que parece violar gravemente la encapsulación.
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 de línea para fines demostrativos. phone.rb:X
refiere a la línea X
del script.
Mira phone.rb:13
! Este método de dial
es lo que envió la llamada! ¡Y phone.rb:22
refiere al controlador imprudente que utilizó el método de dial
!
Como opción, hay una gema binding_of_caller
que le permite ejecutar código en el contexto de cualquier persona que llama en la pila de llamadas (persona que llama, persona que llama, etc.). Es útil para inspeccionar (leer hacer cualquier cosa en cualquier posición en la pila de llamadas) pila de llamadas en desarrollo, tal como se utiliza en better_errors
.
Los objetos de Class
Binding
encapsulan el contexto de ejecución en algún lugar particular del código y retienen este contexto para uso futuro.
Debo mencionar que esta técnica solo debe usarse para fines de depuración, diversión o educación , ya que viola los principios de la POO realmente mal.
Sobre todo debido a eval
.
Vamos a preparar cosas:
require ''binding_of_caller'' # I assume, you installed this gem already?
Obtenga la instancia de llamante inmediata (más cercana en la pila, por lo tanto, 0
):
binding.of_caller(0).eval(''self'')
... o incluso un método de llamada inmediata:
binding.of_caller(0).eval(''__method__'')
Si necesita subir más arriba en la pila de llamadas, use números distintos a 0
para obtener el enlace de una persona que llama.
Terriblemente hacky Pero si realmente necesitas esto, ahí tienes.