R
Robert Evans
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_those3field1, :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.debugdate)
=====
@date = Fri Apr 06 17:15:25 -0700 2007
%> m.debugall)
=====
@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_datedate)
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
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_those3field1, :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.debugdate)
=====
@date = Fri Apr 06 17:15:25 -0700 2007
%> m.debugall)
=====
@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_datedate)
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