ruby-on-rails ruby - Comment trouver où une méthode est définie lors de l'exécution?




example tutorial (9)

Réponse très tard :) Mais les réponses précédentes ne m'a pas aidé

set_trace_func proc{ |event, file, line, id, binding, classname|
  printf "%8s %s:%-2d %10s %8s\n", event, file, line, id, classname
}
# call your method
set_trace_func nil

Nous avons récemment eu un problème où, après une série de validations, un processus dorsal n'a pas fonctionné. Maintenant, nous étions de bons petits garçons et filles et nous faisions des rake test après chaque check-in mais, à cause de certaines bizarreries dans le chargement de la bibliothèque de Rails, cela n'arrivait que lorsque nous l'utilisions directement en Mongolie.

J'ai dépisté le bug et c'était dû à un nouveau gem Rails qui écrasait une méthode dans la classe String d'une manière qui cassait une utilisation étroite dans le code Rails d'exécution.

Quoi qu'il en soit, en bref, 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 ) qui retourne /path/to/some/file.rb line #45 ? Dans ce cas, me dire qu'il était défini dans la classe String ne serait pas utile, car il était surchargé par une bibliothèque.

Je ne peux pas garantir que la source soit présente dans mon projet, donc le fait de vouloir 'def foo' ne me donnera pas forcément ce dont j'ai besoin, pas plus si j'ai beaucoup de def foo , parfois je ne sais pas avant peut être utilisé.


Cela peut vous aider mais vous devrez le coder vous-même. Collé du blog:

Ruby fournit un callback method_added () invoqué à chaque fois qu'une méthode est ajoutée ou redéfinie dans une classe. Cela fait partie de la classe Module, et chaque classe est un module. Il y a aussi deux callbacks appelés method_removed () et method_undefined ().

http://scie.nti.st/2008/9/17/making-methods-immutable-in-ruby


Vous pouvez toujours obtenir une trace d'où vous êtes en utilisant caller() .


Peut-être que le #source_location peut aider à trouver d'où vient la méthode.

ex:

ModelName.method(:has_one).source_location

Revenir

[project_path/vendor/ruby/version_number/gems/activerecord-number/lib/active_record/associations.rb", line_number_of_where_method_is]

OU

ModelName.new.method(:valid?).source_location

Revenir

[project_path/vendor/ruby/version_number/gems/activerecord-number/lib/active_record/validations.rb", line_number_of_where_method_is]

Vous pouvez 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 les instances de Method :

require 'rubygems'
require 'activesupport'

m = 2.days.method(:ago)
# => #<Method: Fixnum(ActiveSupport::CoreExtensions::Numeric::Time)#ago>

m.__file__
# => "/Users/james/.rvm/gems/ree-1.8.7-2010.01/gems/activesupport-2.3.8/lib/active_support/core_ext/numeric/time.rb"
m.__line__
# => 64

Pour Ruby 1.9 et au-delà, il y a source_location (merci Jonathan!):

require 'active_support/all'
m = 2.days.method(:ago)
# => #<Method: Fixnum(Numeric)#ago>    # comes from the Numeric module

m.source_location   # show file and line
# => ["/var/lib/gems/1.9.1/gems/activesupport-3.0.6/.../numeric/time.rb", 63]

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 planter, vous ne pouvez pas savoir où il a été défini. Si vous tentez de singe avec la méthode en l'écrasant ou en l'écrasant, alors tout plantage viendra de votre méthode écrasée ou surchargée, et cela ne servira à rien.

Façons utiles de plantage des méthodes:

  1. Passe nil là où il l'interdit - la plupart du temps la méthode soulèvera une ArgumentError ou le toujours NoMethodError sur une classe nulle.
  2. Si vous avez une connaissance approfondie de la méthode, et que vous savez que la méthode appelle à son tour une autre méthode, vous pouvez écraser l'autre méthode et l'augmenter à l'intérieur.

C'est vraiment en retard, mais voici comment vous pouvez trouver où une méthode est définie:

http://gist.github.com/76951

# How to find out where a method comes from.
# Learned this from Dave Thomas while teaching Advanced Ruby Studio
# Makes the case for separating method definitions into
# modules, especially when enhancing built-in classes.
module Perpetrator
  def crime
  end
end

class Fixnum
  include Perpetrator
end

p 2.method(:crime)
#<Method: Fixnum(Perpetrator)#crime>

Si vous utilisez Ruby 1.9+, vous pouvez utiliser source_location

require 'csv'

p CSV.new('string').method(:flock)
# => #<Method: CSV#flock>

CSV.new('string').method(:flock).source_location
# => ["/path/to/ruby/1.9.2-p290/lib/ruby/1.9.1/forwardable.rb", 180]

Notez que cela ne fonctionnera pas sur tout, comme le code compilé natif. La classe Method a aussi des fonctions intéressantes, comme Method#owner qui retourne le fichier où la méthode est définie.

EDIT: Voir aussi le __file__ et __line__ et les notes pour REE dans l'autre réponse, ils sont également utiles. - wg


Je viens en retard à ce fil, et je suis surpris que personne n'a mentionné Method#owner .

class A; def hello; puts "hello"; end end
class B < A; end
b = B.new
b.method(:hello).owner
=> A

Sur Windows7 le fichier .gemrc n'est pas présent, vous pouvez laisser Ruby en créer un (ce n'est pas facile à faire dans l'explorateur).

gem sources --add http://rubygems.org

Vous devrez confirmer (c'est dangereux). Maintenant, le fichier est créé dans votre dossier userprofile (c: \ users \)

Vous pouvez modifier le fichier texte pour supprimer la source que vous avez ajoutée ou vous pouvez le supprimer avec

gem sources --remove http://rubygems.org




ruby-on-rails ruby runtime methods definition