Get class location from class object

后端 未结 7 2073
北恋
北恋 2020-12-13 23:29

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 i

相关标签:
7条回答
  • 2020-12-14 00:04

    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

    > 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
    
    0 讨论(0)
  • 2020-12-14 00:06

    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.

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

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

    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.

    EDIT: Some good news after all. In Ruby 1.9 there is source_location and 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.

    0 讨论(0)
  • 2020-12-14 00:06

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

    0 讨论(0)
  • 2020-12-14 00:17

    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:

    [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 s will "step" me into the next line of code, which will be in the initialize block for 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_search to 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.

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

    0 讨论(0)
  • 2020-12-14 00:27
    Klass.method(Klass.methods.first).source_location
    

    Using source_location for 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.

    0 讨论(0)
  • 2020-12-14 00:27

    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.

    $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
    }
    
    0 讨论(0)
提交回复
热议问题