Comment faire pour trouver d'où une méthode est définie au moment de l'exécution?
Nous avons eu récemment un problème où, après une série de commits avait eu lieu, un backend processus de l'exécution a échoué. Maintenant, nous avons été bons petits garçons et les filles et a couru rake test
après chaque check-in, mais, en raison de certaines bizarreries dans les Rails de chargement de bibliothèque, il ne s'est produite lorsque nous avons lancé directement à partir de Bâtards dans le mode de production.
J'ai suivi le bug et c'était dû à un nouveau gem Rails de remplacer une méthode de la classe String dans une manière qui est cassé un étroit dans l'exécution des Rails de code.
De toute façon, c'est une longue histoire courte, il est un moyen, au moment de l'exécution, de demander Ruby où un méthode a été définie? Quelque chose comme whereami( :foo )
qui renvoie /path/to/some/file.rb line #45
? Dans ce cas, de me dire qu'il a été défini dans la classe String serait inutile, parce qu'il est débordé par la bibliothèque.
Je ne peux pas garantir la source de la vie dans mon projet, grepping pour 'def foo'
ne va pas forcément me donner ce dont j'ai besoin, pour ne pas mentionner si j'ai de nombreux def foo
's, parfois je ne sais pas jusqu'à l'exécution lequel j'ai peut-être l'aide d'.
- En Ruby 1.8.7, une méthode spéciale a été ajoutée spécialement pour trouver cette information (et il est toujours là dans 1.9.3)... plus de détails dans ma réponse ci-dessous.
Vous devez vous connecter pour publier un commentaire.
C'est vraiment la fin, mais voici comment vous pouvez trouver des cas où une méthode est définie:
http://gist.github.com/76951
Si vous êtes sur Ruby 1.9+, vous pouvez utiliser
source_location
Notez que cela ne fonctionne pas sur tout, comme native code compilé. Le Méthode de classe a bien des fonctions, aussi, comme Méthode#propriétaire qui renvoie le fichier où la méthode est définie.
EDIT: voir Aussi la
__file__
et__line__
et les notes pour la REE dans l'autre réponse, ils sont utiles aussi. -- gtowner
méthode2.method(:crime)
?Fixnum
method_missing
. Donc, si vous avez un module ou l'ancêtre de la classe avec unclass_eval
oudefine_method
à l'intérieur demethod_missing
, cette méthode ne fonctionnera pas.def something() create :stuff end
, comment puis-je savoir oùcreate
est en cours de définition?Vous pouvez effectivement aller un peu plus loin que la solution ci-dessus. Pour Ruby 1.8 Enterprise Edition, il y a le
__file__
et__line__
méthodes surMethod
instances:Pour Ruby 1.9 et au-delà, il n'y a
source_location
(merci Jonathan!):__file__
et__line__
sur touteMethod
instance de classe, ex:method(:method).__file__
.m.__file__
etm.__line__
ont été remplacés par desm.source_location
.source_location
fonctionne avec Ruby 1.9 et vers le haut, y compris 2.1Je suis arrivé en retard à ce fil, et je suis surpris que personne n'a mentionné
Method#owner
.Method#parameters
.La copie de ma réponse à partir d'une nouvelle question similaire qui ajoute de nouvelles informations à ce problème.
Ruby 1.9 a la méthode appelée source_location:
Cela a été reporté à 1.8.7 par ce bijou:
De sorte que vous pouvez demander pour la méthode:
Et ensuite demander le
source_location
de cette méthode:Cela va retourner un tableau avec le nom de fichier et le numéro de ligne.
E. g pour
ActiveRecord::Base#validates
ce retourne:Pour les classes et les modules, Ruby n'offre pas de support intégré, mais il est un excellent Résumé qui s'appuie sur
source_location
pour retourner fichier pour une méthode donnée ou le premier fichier pour une classe, si aucune méthode n'a été spécifié:En action:
Sur Mac avec TextMate est installé, il apparaît également que l'éditeur à l'emplacement spécifié.
Cela peut aider, mais vous devez coder vous-même. Collé à partir du blog:
http://scie.nti.st/2008/9/17/making-methods-immutable-in-ruby
Si vous pouvez planter la méthode, vous aurez une trace qui va vous dire exactement où il est.
Malheureusement, si vous ne pouvez pas crash, alors vous ne pouvez pas trouver où elle a été définie. Si vous tentez de le singe avec la méthode de l'écraser ou de la transgression, alors qu'un incident va venir à partir de votre écrasement ou la méthode de remplacement, et il ne sera pas de toute utilisation.
Utile les moyens de s'écraser méthodes:
nil
où il l'interdit - la plupart du temps, la méthode génère uneArgumentError
ou de laNoMethodError
sur un nul en classe.require 'ruby-debug'; debugger
dans votre code où vous souhaitez déposer dans.Peut-être le
#source_location
peut vous aider à trouver où est la méthode viennent.ex:
Retour
OU
Retour
Très tardive réponse 🙂 Mais les réponses précédentes ne m'aide pas
nil
?nil
.»Vous pourriez être en mesure de faire quelque chose comme ceci:
foo_finder.rb:
Puis assurer foo_finder est chargé en premier, avec quelque chose comme
(Je n'ai foiré avec des rails, donc je ne sais pas exactement, mais j'imagine qu'il y a une façon de commencer, c'est un peu comme ça.)
Cela va vous montrer toutes les re-définitions de la Chaîne#foo. Avec un peu de méta-programmation, vous pourrait généraliser ce quelque soit la fonction que vous voulez. Mais il ne doivent être chargés AVANT que le fichier ne fait la re-définition.
Vous pouvez toujours obtenir une trace de l'endroit où vous êtes en utilisant
caller()
.