当前位置:  开发笔记 > 后端 > 正文

如何在运行时找到方法的定义?

如何解决《如何在运行时找到方法的定义?》经验,为你挑选了7个好方法。

我们最近遇到了一个问题,即在发生一系列提交后,后端进程无法运行.现在,我们都是优秀的小男孩和女孩,并rake test在每次办理登机手续后都跑了,但由于Rails图书馆装载中的一些奇怪现象,它只发生在我们直接从生产模式中的Mongrel运行时.

我追踪了这个错误,这是因为一个新的Rails gem以一种破坏运行时Rails代码中一个狭隘用法的方式覆盖了String类中的一个方法.

无论如何,长话短说,有没有办法在运行时询问Ruby在哪里定义了一个方法?这样的whereami( :foo )回归/path/to/some/file.rb line #45?在这种情况下,告诉我它是在类String中定义的将是无益的,因为它被某些库重载.

我不能保证源代码存在于我的项目中,因此grepping 'def foo'不一定会给我我需要的东西,更不用说我是否有很多东西 def foo,有时候直到运行时我才知道我可能正在使用哪一个.



1> wesgarrison..:

这真的很晚了,但是你可以在这里找到定义方法的地方:

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) # The "2" here is an instance of Fixnum.
#

如果您使用的是Ruby 1.9+,则可以使用 source_location

require 'csv'

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

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

请注意,这不适用于所有内容,例如本机编译代码.该方法类有一些巧妙的功能,太像方法#主人,返回的定义方法的文件.

编辑:另外在另一个答案中看到__file____line__REE的注意事项,它们也很方便. - wg



2> James Adam..:

实际上你可以比上面的解决方案更进一步.对于Ruby 1.8 Enterprise Edition,实例上有__file____line__方法Method:

require 'rubygems'
require 'activesupport'

m = 2.days.method(: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

对于Ruby 1.9及更高版本,有source_location(感谢Jonathan!):

require 'active_support/all'
m = 2.days.method(: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]


在Ruby 1.9上,`m .__ file__`和`m .__ line__`已替换为`m.source_location`.
我在任何`Method`类实例上都得到了__file__和__line__的“ NoMethodError:undefined method”,例如:method(:method).__ file__。

3> Alex D..:

我迟到了这个帖子,很惊讶没人提到Method#owner.

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


我很惊讶您是第一个明确引用[Method类](http://www.ruby-doc.org/core-1.9.3/Method.html)的人。1.9中引入的另一个鲜为人知的宝藏:“ Method#parameters”。

4> Laas..:

从一个更新的类似问题中复制我的答案,该问题为此问题添加了新信息.

Ruby 1.9有一个名为source_location的方法:

返回包含此方法的Ruby源文件名和行号,如果未在Ruby中定义此方法,则返回nil(即本机)

这个宝石被反向移植到1.8.7:

ruby18_source_location

所以你可以请求方法:

m = Foo::Bar.method(:create)

然后询问source_location该方法:

m.source_location

这将返回一个包含文件名和行号的数组.例如,ActiveRecord::Base#validates这个回报:

ActiveRecord::Base.method(:validates).source_location
# => ["/Users/laas/.rvm/gems/ruby-1.9.2-p0@arveaurik/gems/activemodel-3.2.2/lib/active_model/validations/validates.rb", 81]

对于类和模块,Ruby不提供内置支持,但是source_location如果没有指定方法,那么有一个优秀的Gist可用于返回给定方法的文件或类的第一个文件:

ruby where_is模块

在行动:

where_is(ActiveRecord::Base, :validates)

# => ["/Users/laas/.rvm/gems/ruby-1.9.2-p0@arveaurik/gems/activemodel-3.2.2/lib/active_model/validations/validates.rb", 81]

在安装了TextMate的Mac上,这也会弹出指定位置的编辑器.



5> Ken..:

这可能会有所帮助,但您必须自己编写代码.粘贴在博客上:

Ruby提供了一个method_added()回调,每次在类中添加或重新定义方法时都会调用该回调.它是Module类的一部分,每个Class都是一个Module.还有两个相关的回调叫做method_removed()和method_undefined().

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



6> Orion Edward..:

如果你可以崩溃这个方法,你会得到一个回溯,它会告诉你确切的位置.

不幸的是,如果你不能崩溃它,那么你无法找到它的定义.如果您尝试通过覆盖或覆盖它来使用该方法,那么任何崩溃都将来自您的覆盖或重写方法,并且它将没有任何用处.

崩溃方法的有用方法:

    通过nil它禁止它的地方 - 很多时候这个方法会在一个零级别上提出ArgumentError或永远存在NoMethodError.

    如果你对方法有内在的了解,并且你知道该方法又调用了其他一些方法,那么你可以覆盖另一个方法,然后在其中加注.



7> 小智..:

也许这#source_location有助于找到方法的来源.

例如:

ModelName.method(:has_one).source_location

返回

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

要么

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

返回

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

推荐阅读
coco2冰冰
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有