Ruby Debugging Magic Cheat Sheet

Ruby自带的一些debug功能其实还是很好用的,这里稍做记录。

找到方法是在哪一行记录的

object = Object.new
puts object.method(:blank?).source_location
=> ["/gems/activesupport-5.0.0.beta1/lib/active_support/core_ext/object/blank.rb", 14]

打开项目依赖的gem

$ bundle open active_support

这行命令可以打开Gemfile.lock制定的gem版本的active_support的源代码。使用当前环境变量里EDITOR指定的文本编辑器。

还原gem

$ gem pristine activesupport

假如你对activesupport这个gem添加了一些debug code之类的,可以轻松通过这条命令将gem重置为本来的状态。

$ gem pristine --all

这行命令会重置所有的gem,特别是当一些gem有c扩展的时候,会花费更多时间。

找到方法是如何被调用的

class Project

  def foo
    puts "====================="
    puts caller
  end
end

可以用caller,在不抛出异常的情况下打印出当前的backtrace信息。

找到super方法定义的位置

def foo
  puts method(:foo).super_method.source_location
  super
end

列出一个对象的所有方法

object.methods
# => [:instance_of?, :public_send, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :remove_instance_variable, :private_methods, :kind_of?, :instance_variables, :tap, :is_a?, :extend, :define_singleton_method, :to_enum, :enum_for, :<=>, :===, :=~, :!~, :eql?, :respond_to?, :freeze, :inspect, :display, :send, :object_id, :to_s, :method, :public_method, :singleton_method, :nil?, :hash, :class, :singleton_class, :clone, :dup, :itself, :taint, :tainted?, :untaint, :untrust, :trust, :untrusted?, :methods, :protected_methods, :frozen?, :public_methods, :singleton_methods, :!, :==, :!=, :__send__, :equal?, :instance_eval, :instance_exec, :__id__]

通过类直接找到对象方法定义的位置

User.instance_method(:github_url).source_location
得到方法所需的参数
def parse(input, skip_code_comments: false, ignore_whitespace: true)
  # do stuff
end
method(:parse).parameters
#=> [[:req, :input], [:key, :skip_code_comments], [:key, :ignore_whitespace]]

寻找变量是何时被改变的

可以debug的时候灵活使用object.freeze 这样当object被改变时,就可以抛出异常得知object是在哪里被改变了。注意!这个trick只对变量被改变有效果,如果变量是完全被replaced,那么就没有用了。

找到一个常量或对象是在哪里创建

require 'objspace'
ObjectSpace.trace_object_allocations_start

Kernel.send(:define_method, :sup) do |obj|
  puts "#{ ObjectSpace.allocation_sourcefile(obj) }:#{ ObjectSpace.allocation_sourceline(obj) }"
end

world = "hello"

sup world
# => /tmp/scratch.rb:10

本文编译自:http://www.schneems.com/2016/01/25/ruby-debugging-magic-cheat-sheet.html