ruby 从类对象获取类位置

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13012109/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-06 05:28:17  来源:igfitidea点击:

Get class location from class object

ruby

提问by Haris Krajina

I have a bunch of code to look at, and now it is debugging time. Since I have never been a fan of Ruby's debugger I am looking for a way of going through code and reading it.

我有一堆代码要看,现在是调试时间。因为我从来都不是 Ruby 调试器的粉丝,所以我正在寻找一种方式来浏览代码并阅读它。

What I am trying to do is get the location of the file where a loaded class is defined:

我想要做的是获取定义加载类的文件的位置:

Foo::Bar.create(:param) # how can I know file location in runtime?

For smaller, better organized, projects, I would just search for class Barbut here that is not possible since there are many classes named Bar, and, to make matters worse, some of them are under the same namespace. I know, it's trouble waiting to happen.

对于更小、组织更好的项目,我只会搜索,class Bar但在这里这是不可能的,因为有许多名为 的类Bar,而且更糟糕的是,其中一些类位于相同的命名空间下。我知道,等待发生很麻烦。

Note: I'm using Ruby 1.8.7.

注意:我使用的是 Ruby 1.8.7。

采纳答案by Laas

For Methodsand ProcsRuby 1.9 has method called source_location:

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

Returns the Ruby source filename and line number containing this method or nil if this method was not defined in Ruby (i.e. native)

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

So you can request for the method:

所以你可以请求方法:

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

And then ask for the source_locationof that method:

然后询问source_location该方法的 :

m.source_location

This will return an array with filename and line number. E.g for ActiveRecord::Base#validatesthis returns:

这将返回一个包含文件名和行号的数组。例如对于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]

For classes and modules, Ruby does not offer built in support, but there is an excellent Gist out there that builds upon source_locationto return file for a given method or first file for a class if no method was specified:

对于类和模块,Ruby 不提供内置支持,但是有一个很好的 Gist 可以在source_location没有指定方法的情况下返回给定方法的文件或类的第一个文件:

EDIT:For Ruby 1.8.7 there is a gem that backports source_location:

编辑:对于 Ruby 1.8.7,有一个向后移植的 gem source_location

回答by illusionist

FYI, In Rails's console or debugging sessions of Rails apps, you can find out the disk-location of the file where that particular class is defined. like

仅供参考,在 Rails 的控制台或 Rails 应用程序的调试会话中,您可以找到定义该特定类的文件的磁盘位置。喜欢

> show-source Job

this will give you

这会给你

From: /home/john/projects/iisifix/app/models/job.rb @ line 13:
Class name: Job
Number of monkeypatches: 6. Use the `-a` option to display all available monkeypatches
Number of lines: 66

class Job < ApplicationRecord
  belongs_to :quote_request
  belongs_to :garage

回答by the Tin Man

Here's a simple example showing how I track locations in code. If I need to know a location in a module:

这是一个简单的示例,展示了我如何在代码中跟踪位置。如果我需要知道模块中的位置:

class Foo
  attr_reader :initialize_loc
  def initialize
    @initialize_loc = [__FILE__, __LINE__]
    # do more stuff...
  end
end

If I need to know where something happened:

如果我需要知道发生了什么事情:

require_relative 't1'

foo = Foo.new
# do lots of stuff until you want to know where something was initialized.
puts 'foo initialized at %s:%s' % foo.initialize_loc

When I run the code I get:

当我运行代码时,我得到:

FooBar:Desktop foobar ruby t2.rb 
foo initilized at /Users/foobar/Desktop/t1.rb:4

If I don't want to mess with the source-code of the module, and want the debugger to jump in when I need it, I'll have the debugger do just that:

如果我不想弄乱模块的源代码,并希望调试器在我需要它时加入,我会让调试器这样做:

require_relative 't1'
require 'ruby-debug'

debugger
foo = Foo.new
# do lots of stuff until you want to know where something was initilized.
puts 'foo initilized at %s:%s' % foo.initialize_loc

The execution will stop and I'll drop into the debugger at the line immediately following debugger:

执行将停止,我将在紧随其后的行处进入调试器debugger

[0, 9] in t2.rb
  1  require_relative 't1'
  2  require 'ruby-debug'
  3  
  4  debugger
=> 5  foo = Foo.new
  6  # do lots of stuff until you want to know where something was initilized.
  7  puts 'foo initilized at %s:%s' % foo.initialize_loc
  8  
t2.rb:5
foo = Foo.new
(rdb:1) 

A simple swill "step" me into the next line of code, which will be in the initializeblock for Foo:

一个简单的s将“步进”我到下一行代码,这将在initialize块中Foo

(rdb:1) s
[-1, 8] in /Users/foobar/Desktop/t1.rb
  1  class Foo
  2    attr_reader :initialize_loc
  3    def initialize
=> 4      @initialize_loc = [__FILE__, __LINE__]
  5      # do more stuff...
  6    end
  7  end
  8  
/Users/foobar/Desktop/t1.rb:4
@initialize_loc = [__FILE__, __LINE__]
(rdb:1) 

Beyond this, using tools like grep -rn target_to_find path_to_searchto recursively search directories and list the filename and line numbers of lines matching the target, will go a long ways to helping find what you're looking for.

除此之外,使用诸如grep -rn target_to_find path_to_search递归搜索目录并列出与目标匹配的行的文件名和行号之类的工具,将大大有助于找到您要查找的内容。

Or, using :vim /target_to_find/ path_to_searchfrom inside Vim will return the files you're looking for.

或者,:vim /target_to_find/ path_to_search从 Vim 内部使用将返回您要查找的文件。

回答by shushugah

Klass.method(Klass.methods.first).source_location

Using source_locationfor a method, I can search for first method defined in a class. I imagine this is not foolproof due to meta-programming and other hacks.

使用source_locationfor 方法,我可以搜索类中定义的第一个方法。我想这不是万无一失的,因为元编程和其他黑客。

回答by bigtoe416

I got this error when changing a superclass of an object and the fix was to stop and start spring.

更改对象的超类时出现此错误,解决方法是停止和启动 spring。

回答by dbenhur

Frankly, given your described code organization, I think ruby-debug is the easy route to discovering the destination of your call-site: just set breakpoint and step in. If you're really allergic to the debugger, you could instrument the call site with Kernel#set_trace_func.

坦率地说,鉴于您描述的代码组织,我认为 ruby​​-debug 是发现调用站点目的地的简单途径:只需设置断点并介入。如果您真的对调试器过敏,则可以检测调用站点与Kernel#set_trace_func.

$max_trace = 10
set_trace_func proc { |event, file, line, id, binding, classname|
  printf "%8s %s:%-2d %10s %8s\n", event, file, line, id, classname
  $max_trace -= 1 
  set_trace_func(nil) unless $max_trace > 0
}

回答by Regedor

Bad news! I guess in run time there is no way to know what file create or defined a class in Ruby 1.8.7.

坏消息!我猜在运行时没有办法知道是什么文件在 Ruby 1.8.7 中创建或定义了一个类。

If the project has some structure like rails, you would be able to guess it.

如果项目有一些类似 rails 的结构,你就能猜到。

But in Ruby multiple files can be defining methods for the same class Class can even be defined during run time (metaprogramming).

但是在 Ruby 中,多个文件可以为同一个类定义方法,甚至可以在运行时(元编程)定义类。

That means that there might be more than one place where the class is defined. And what you look for can be spread over more than one file.

这意味着定义类的地方可能不止一个。您要查找的内容可以分布在多个文件中。

I guess you will have to search for all definitions of Bar and see if they are inside the module Foo, or start by find all Foo definitions and check whats inside. If the code is a mess, I don't see a easy way, you will have to follow the spaguetti form point to poi. A good editor and multiple file search might help, but you will need to read through the code.

我想你将不得不搜索 Bar 的所有定义,看看它们是否在模块 Foo 中,或者首先找到所有 Foo 定义并检查里面是什么。如果代码一团糟,我没有看到简单的方法,您将不得不按照意大利面条的形式指向 poi。一个好的编辑器和多文件搜索可能会有所帮助,但您需要通读代码。

EDIT:Some good news after all. In Ruby 1.9 there is source_locationand looks like there is backport of it for 1.8.7. However, if the definition was made during runtime by a eval or so I'm not sure if it will work. I think the simplest solution is a good editor like Rubymine that usually can tell you where the code was defined.

编辑:毕竟有一些好消息。在 Ruby 1.9 中source_location,似乎有 1.8.7 的反向移植。但是,如果定义是在运行时通过 eval 进行的,我不确定它是否会起作用。我认为最简单的解决方案是像 Rubymine 这样的优秀编辑器,它通常可以告诉您代码的定义位置。