咱们最近遇到了一个问题,即在发生一系列提交后,后端进程没法运行。 如今,咱们是优秀的小男孩和女孩,并在每次办理登机手续后都进行了rake test
,可是因为Rails库加载中的一些奇怪现象,它只发生在咱们直接从Mongrel生产模式中运行时。 git
我追踪了这个错误,这是由于一个新的Rails gem以一种破坏运行时Rails代码中一个狭隘用法的方式覆盖了String类中的一个方法。 github
不管如何,长话短说,有没有办法在运行时询问Ruby在哪里定义了一个方法? 像whereami( :foo )
那样返回/path/to/some/file.rb line #45
? 在这种状况下,告诉我它是在类String中定义的将是无益的,由于它被某些库重载。 编程
我不能保证源代码存在于个人项目中,因此对'def foo'
追求并不必定会给我我须要的东西,更不用说我有多少 def foo
,有时候直到运行时我都不知道哪个我可能正在使用。 后端
从一个更新的相似问题中复制个人答案,该问题为此问题添加了新信息。 数组
Ruby 1.9有一个名为source_location的方法: ruby
返回包含此方法的Ruby源文件名和行号,若是未在Ruby中定义此方法,则返回nil(即本机) app
这个宝石被反向移植到1.8.7 : 编辑器
因此你能够请求方法: spa
m = Foo::Bar.method(:create)
而后询问该方法的source_location
: code
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不提供内置支持,可是若是没有指定方法,那么有一个优秀的Gist构建在source_location
以返回给定方法的文件或类的第一个文件:
在行动:
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上,这也会弹出指定位置的编辑器。
这可能会有所帮助,但您必须本身编写代码。 粘贴在博客上:
Ruby提供了一个method_added()回调,每次在类中添加或从新定义方法时都会调用该回调。 它是Module类的一部分,每一个Class都是一个Module。 还有两个相关的回调叫作method_removed()和method_undefined()。
http://scie.nti.st/2008/9/17/making-methods-immutable-in-ruby
若是你能够崩溃这个方法,你会获得一个回溯,它会告诉你确切的位置。
不幸的是,若是你不能崩溃它,那么你没法找到它的定义。 若是您尝试经过覆盖或覆盖它来使用该方法,那么任何崩溃都未来自您的覆盖或重写方法,而且它将没有任何用处。
崩溃方法的有用方法:
nil
禁止它 - 不少时候该方法会在nil类上引起ArgumentError
或者永远存在的NoMethodError
。 你能够作这样的事情:
foo_finder.rb:
class String def String.method_added(name) if (name==:foo) puts "defining #{name} in:\n\t" puts caller.join("\n\t") end end end
而后确保首先加载foo_finder
ruby -r foo_finder.rb railsapp
(我只是搞砸了轨道,因此我不确切知道,但我想有一种方法能够像这样开始。)
这将显示String#foo的全部从新定义。 经过一些元编程,您能够将其归纳为您想要的任何功能。 但它确实须要在实际进行从新定义的文件以前加载。
您能够使用caller()
始终回溯您所在的位置。