Ad-hoc debugging module


#1

Hi,

I recently found myself playing with a bunch of objects, iterating
their behavior in irb, and I wanted to see just some of the fields
each time I did something instead of the whole object that you would
get with pp or y .

So, I wrote a little module that I could include in interesting
classes, so that I could ask objects things like obj.debug
(:field1, :field5, :field6) instead of printing out all the methods.
Then I got bored doing that and extended it so I could create ad hoc
watch methods, e.g., obj.show_those3(:field1, :field5, :field6).

I thought others might find it useful too. Also, if anyone has any
improvements on it, I am of course interested.

Thanks,
Bob E.
http://www.junitfactory.com/

module Debuggable
def method_missing(method_name, *args)
method_name = method_name.to_s
if method_name.eql?(‘debug’)
debug(args)
elsif method_name =~ /^show
/
new_method_name = create_new_watch_method(method_name, args)
self.method(new_method_name).call
elsif method_name =~ /^unshow_/
self.class.class_eval do
watch_name = method_name.slice(method_name.index(/unshow_/)

  • 7, method_name.length)
    undef_method “show_#{watch_name}”
    end
    end
    end

    def _debug(args)
    puts “=====”
    if args.empty? || args[0].eql?(:all)
    puts self.instance_variables.map { |a| “#{a} = #
    {self.instance_variable_get(a)}”}.join(", “)
    else
    strs = args.map do |a|
    var = self.instance_variable_get(”@#{a}")
    if var.nil?
    “@#{a} is not an instance variable”
    else
    “@#{a} = #{var.inspect}”
    end
    end
    puts strs.join(", ")
    end
    end

    def create_new_watch_method(method_name, args)
    watch_name = method_name.slice(method_name.index(/show_/) + 5,
    method_name.length)
    new_method_name = “show_#{watch_name}”
    if args.empty?
    args = [:all]
    end
    self.class.class_eval do
    define_method(new_method_name) do
    _debug(args)
    end
    end
    puts “created permanent watch method: #{new_method_name}”
    new_method_name
    end
    end

===================
given a class

class MyClass
attr_reader :name, :date

def initialize(name, date)
@name = name
@date = date
end
end

===================
loaded in an irb prompt, we can do the following:

%>m = MyClass.new(“Bob”, Time.now)
%> class MyClass
include Debuggable
end

%>m.debug(:date)

@date = Fri Apr 06 17:15:25 -0700 2007

%> m.debug(:all)

@name = Bob, @date = Fri Apr 06 17:15:25 -0700 2007

%> m.debug

@name = Bob, @date = Fri Apr 06 17:15:25 -0700 2007

%>m.show_date(:date)
created permanent watch method: show_date

@date = Fri Apr 06 17:15:25 -0700 2007

%>m.methods.grep /show/
[“show_date”]

%>m.show_date

@date = Fri Apr 06 17:15:25 -0700 2007

%>m.unshow_date
%>m.methods.grep /show/
[]

%>m.show_all
created permanent watch method: show_all

@name = Bob, @date = Fri Apr 06 17:15:25 -0700 2007

%>m.methods.grep /show/
[“show_all”]

%>m.show_all

@name = Bob, @date = Fri Apr 06 17:15:25 -0700 2007

%>m.unshow_all
%>m.methods.grep /show/
[]

%>m.show_bazooka
created permanent watch method: show_bazooka

@name = Bob, @date = Fri Apr 06 17:15:25 -0700 2007