Une manière de déterminer l'objet appelé une méthode?
-
01-10-2019 - |
Question
J'espère que les moyens d'infrastructure de passage de messages de Ruby il pourrait y avoir un truc intelligent pour cela.
Comment puis-je déterminer l'objet appelant - quel objet appelé la méthode que je suis actuellement en
La solution
En option, il est un petit bijou binding_of_caller
qui vous permet d'exécuter du code dans le contexte de tout appelant sur la pile d'appel (numéro appelant, l'appelant de l'appelant et ainsi de suite). Il est utile pour le contrôle (lire faire quoi que ce soit à toute position sur l'appel pile ) pile d'appels dans le développement, tel qu'il est utilisé dans better_errors
.
Objets de classe
Binding
encapsulent le contexte d'exécution à un endroit particulier dans le code et conserver ce contexte pour une utilisation future.
Je dois mentionner, cette technique ne doit être utilisé pour le débogage, des fins ludiques ou éducatives , car il viole les principes de la POO vraiment mal.
La plupart du temps en raison de eval
.
stuff préparer Let:
require 'binding_of_caller' # I assume, you installed this gem already?
Obtenez le immédiate (le plus proche sur la pile, donc 0
) instance de l'appelant:
binding.of_caller(0).eval('self')
... ou même une méthode d'appel immédiat:
binding.of_caller(0).eval('__method__')
Si vous avez besoin pour obtenir plus haut dans la pile des appels, les numéros d'utilisation autres que 0
pour obtenir la liaison de l'appelant.
Terriblement aki. Mais si vous avez vraiment besoin de cette -. Et voilà
Autres conseils
Vous pouvez facilement regarder la ligne de code qui a appelé la fonction d'intérêt par
caller.first
qui vous indiquera le nom et le numéro de ligne qui appelle la fonction correspondante. Vous pouvez ensuite rétrocalcul quel objet il était.
Cependant, il semble que vous êtes plus après un certain objet qui a appelé une certaine fonction, peut-être dans une méthode d'instance. Je ne suis pas au courant d'une méthode pour déterminer ceci - mais je ne l'utiliserais pas de toute façon, car il semble violer mal l'encapsulation
.Technologie à son meilleur:
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>'"]
Remarque:.. Numéro de ligne à des fins démonstratives phone.rb:X
fait référence à la ligne X
du script
Regardez phone.rb:13
! Cette méthode de dial
est ce qui a envoyé l'appel! Et phone.rb:22
fait référence au chauffard qui a utilisé la méthode dial
!
Vous voulez dire comme self
?
irb> class Object
.. def test
.. self
.. end
.. end
=> nil
irb> o = Object.new
=> #<Object:0xb76c5b6c>
irb> o.test
=> #<Object:0xb76c5b6c>
Réponse Peter utilisé dans le code de production par exemple
Dans ma compagnie nous étions désobligeantes drapeau deleted
saveur de joyau Paranoia colonne deleted_at
. Le code ci-dessous comment nous veillons à ce que tout ira bien avant de supprimer la colonne (le déploiement de ce code, puis au bout de 2 ou 3 jours d'être nous en direct la migration Déployez 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