Ad-hoc debugging module

Discussion in 'Ruby' started by Robert Evans, Apr 7, 2007.

  1. Robert Evans

    Robert Evans Guest

    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 Evans
    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
     
    Robert Evans, Apr 7, 2007
    #1
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.