Nous avons récemment rencontré un problème où, après une série de validations, un processus d'arrière-plan n'a pas pu s'exécuter. Maintenant, nous étions de bons petits garçons et filles et avons couru rake test
après chaque enregistrement, mais, en raison de certaines bizarreries dans le chargement de la bibliothèque de Rails, cela ne s'est produit que lorsque nous l'avons exécuté directement depuis Mongrel en mode production.
J'ai suivi le bogue et cela était dû à un nouveau joyau Rails écrasant une méthode dans la classe String d'une manière qui a rompu une utilisation étroite dans le code Rails d'exécution.
Quoi qu'il en soit, pour faire court, y a-t-il un moyen, au moment de l'exécution, de demander à Ruby où une méthode a été définie? Quelque chose comme whereami( :foo )
ça revient /path/to/some/file.rb line #45
? Dans ce cas, il ne serait pas utile de me dire qu'il a été défini dans la classe String, car il était surchargé par une bibliothèque.
Je ne peux pas garantir la vie de la source dans mon projet, donc chercher 'def foo'
ne me donnera pas nécessairement ce dont j'ai besoin, sans mentionner si j'en ai plusieurs def foo
, parfois je ne sais pas avant l'exécution laquelle j'utilise.
la source
Réponses:
C'est vraiment tard, mais voici comment vous pouvez trouver où une méthode est définie:
http://gist.github.com/76951
Si vous utilisez Ruby 1.9+, vous pouvez utiliser
source_location
Notez que cela ne fonctionnera pas sur tout, comme le code natif compilé. La classe Method possède également quelques fonctions intéressantes, comme le propriétaire de la méthode # qui retourne le fichier dans lequel la méthode est définie.
EDIT: Voir également les notes
__file__
et__line__
et pour REE dans l'autre réponse, elles sont également utiles. - wgla source
owner
méthode2.method(:crime)
?Fixnum
method_missing
. Donc, si vous avez un module ou une classe ancêtre avecclass_eval
ou à l'define_method
intérieur demethod_missing
, cette méthode ne fonctionnera pas.Vous pouvez en fait aller un peu plus loin que la solution ci-dessus. Pour Ruby 1.8 Enterprise Edition, il existe les méthodes
__file__
et__line__
sur lesMethod
instances:Pour Ruby 1.9 et au-delà, il y a
source_location
(merci Jonathan!):la source
__file__
et__line__
sur uneMethod
instance de classe, ex:method(:method).__file__
.m.__file__
etm.__line__
ont été remplacés parm.source_location
.J'arrive tard sur ce sujet et je suis surpris que personne ne l'ait mentionné
Method#owner
.la source
Method#parameters
.Copie de ma réponse à partir d'une question similaire plus récente qui ajoute de nouvelles informations à ce problème.
Ruby 1.9 a une méthode appelée source_location :
Cela a été rétroporté à 1.8.7 par ce joyau:
Vous pouvez donc demander la méthode:
Et puis demandez le
source_location
de cette méthode:Cela renverra un tableau avec le nom de fichier et le numéro de ligne. Par exemple, pour
ActiveRecord::Base#validates
ce retour:Pour les classes et les modules, Ruby n'offre pas de support intégré, mais il existe un excellent Gist qui s'appuie sur
source_location
pour renvoyer le fichier pour une méthode donnée ou le premier fichier pour une classe si aucune méthode n'a été spécifiée:En action:
Sur les Mac avec TextMate installé, cela fait également apparaître l'éditeur à l'emplacement spécifié.
la source
Cela peut aider, mais vous devrez le coder vous-même. Collé du blog:
http://scie.nti.st/2008/9/17/making-methods-immutable-in-ruby
la source
Si vous pouvez planter la méthode, vous obtiendrez une trace qui vous dira exactement où elle se trouve.
Malheureusement, si vous ne pouvez pas le bloquer, vous ne pouvez pas savoir où il a été défini. Si vous tentez de simuler la méthode en la remplaçant ou en la remplaçant, tout plantage proviendra de votre méthode remplacée ou remplacée et ne sera d'aucune utilité.
Méthodes utiles pour planter les méthodes:
nil
là où cela vous l'interdit - la plupart du temps, la méthode soulèvera unArgumentError
ou le toujours présentNoMethodError
sur une classe nulle.la source
require 'ruby-debug'; debugger
dans votre code où vous voulez vous y rendre.Peut-être que cela
#source_location
peut aider à trouver d'où vient la méthode.ex:
Revenir
OU
Revenir
la source
Réponse très tardive :) Mais les réponses précédentes ne m'ont pas aidé
la source
nil
?nil
.»Vous pourriez peut-être faire quelque chose comme ceci:
foo_finder.rb:
Assurez-vous ensuite que foo_finder est chargé en premier avec quelque chose comme
(Je n'ai fait que gâcher les rails, donc je ne sais pas exactement, mais j'imagine qu'il y a un moyen de le démarrer un peu comme ça.)
Cela vous montrera toutes les redéfinitions de String # foo. Avec un peu de méta-programmation, vous pouvez le généraliser pour la fonction que vous souhaitez. Mais il doit être chargé AVANT le fichier qui effectue réellement la redéfinition.
la source
Vous pouvez toujours obtenir une trace de l'endroit où vous vous trouvez en utilisant
caller()
.la source