如何找到在运行时定义方法的位置? [英] How to find where a method is defined at runtime?
问题描述
我们最近遇到了一个问题,即在进行了一系列提交之后,后端进程无法运行.现在,我们是个不错的男孩和女孩,每次检入后都运行rake test
,但是由于Rails库加载的某些奇怪情况,只有在我们以生产模式从Mongrel直接运行它时,这种情况才会发生.
We recently had a problem where, after a series of commits had occurred, a backend process failed to run. Now, we were good little boys and girls and ran rake test
after every check-in but, due to some oddities in Rails' library loading, it only occurred when we ran it directly from Mongrel in production mode.
我跟踪了该错误,这是由于一个新的Rails gem覆盖了String类中的一种方法,从而打破了运行时Rails代码中的一种狭义用法.
I tracked the bug down and it was due to a new Rails gem overwriting a method in the String class in a way that broke one narrow use in the runtime Rails code.
总之,长话短说,在运行时有没有办法问Ruby在哪里定义了一个方法?像whereami( :foo )
这样返回/path/to/some/file.rb line #45
的东西?在这种情况下,告诉我它是在String类中定义的,将无济于事,因为它已被某些库重载.
Anyway, long story short, is there a way, at runtime, to ask Ruby where a method has been defined? Something like whereami( :foo )
that returns /path/to/some/file.rb line #45
? In this case, telling me that it was defined in class String would be unhelpful, because it was overloaded by some library.
我不能保证源代码存在于我的项目中,因此对'def foo'
的grepping并不一定能满足我的需求,更不用说我是否有很多 def foo
我直到运行时才知道我可能正在使用哪一个.
I cannot guarantee the source lives in my project, so grepping for 'def foo'
won't necessarily give me what I need, not to mention if I have many def foo
's, sometimes I don't know until runtime which one I may be using.
推荐答案
这确实很晚,但是您可以通过以下方法找到方法的定义位置:
This is really late, but here's how you can find where a method is defined:
# 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) # The "2" here is an instance of Fixnum.
#<Method: Fixnum(Perpetrator)#crime>
如果您使用的是Ruby 1.9+,则可以使用 source_location
If you're on Ruby 1.9+, you can use 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]
请注意,这不适用于所有内容,例如本机编译代码. 方法类也具有一些简洁的功能,例如 Method#owner 会返回文件,其中方法已定义.
Note that this won't work on everything, like native compiled code. The Method class has some neat functions, too, like Method#owner which returns the file where the method is defined.
另请参见__file__
和__line__
以及REE注释,它们也很方便. -wg
Also see the __file__
and __line__
and notes for REE in the other answer, they're handy too. -- wg
这篇关于如何找到在运行时定义方法的位置?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!