--T4IYkFBVPN84tP7K
Content-Type: multipart/mixed; boundary="YhFoJY/gx7awiIuK"
Content-Disposition: inline
--YhFoJY/gx7awiIuK
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable
Hey. I've included a script that lets you traverse part (most?)
of the object space for ruby through mod_ruby. Toss it onto a mod_ruby
server and you should be good to go. The code is derivative work from
bits and pieces in ruby-session so that it can be used standalone, so
the code needs documentation, but it's here for people to comment on.
If you'd like to tour through things w/o installing it, you can check it
out at:
http://wheel.tgd.net/debug.rbx
I'd love feedback and any feature enhancements. This puppie has
saved me a ton of time in mod_ruby debugging, but it's useful to use to
poke at. If you want to debug your own module, include/require it in
the debug script and it should be available for your use.
echo "require 'mymodule'" >> debug.rbx
-sc
--
Sean Chittenden
--YhFoJY/gx7awiIuK
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="debug.rbx"
Content-Transfer-Encoding: quoted-printable
#!/usr/local/bin/ruby -w
# All of the documentation and software included in ruby-session releases is
# copyrighted by Sean Chittenden <sean / chittenden.org>
#
# Copyright 2001
# Sean Chittenden <sean / chittenden.org>. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
# must display the following acknowledgment:
#
# This product includes software developed by Sean Chittenden
# <sean / chittenden.org> and ruby-session's contributors.
#
# 4. Neither the name of the software nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# If you have any questions regarding the redistribution of this software,
# please contact the author at <sean / chittenden.org>.
include ObjectSpace
r = Apache.request
def body (r)
params = get_params(r)
if params.has_key?('class')
r.puts(inspect_class(params['class'], get_classes()))
elsif params.has_key?('module')
r.puts(inspect_module(params['module'], get_modules()))
else
r.puts(format_modules(get_classes(), 'Classes', 'class'))
r.puts(format_modules(get_modules(), 'Modules', 'module'))
end
end
def escape_html (str)
str.gsub(/&/, '&').gsub(/\"/, '"').gsub(/</, '<').gsub(/>/, '>')
end
def escape_uri(string)
string.gsub(/([^ a-zA-Z0-9_.-]+)/n) do
'%' + $1.unpack('H2' * $1.size).join('%').upcase
end.tr(' ', '+')
end
def format_modules (module_list, title = 'Modules', uriname = 'module')
output = ''
ordered_modules = []
module_list.each do |ml|
ordered_modules.push(ml.to_s)
end
output <<= "<h1>#{title}:</h1>"
output <<= '<table border="1">'
ordered_modules.uniq.sort.each do |mn|
output <<= "<tr><td><a href=\"#{Apache.request.uri}?#{uriname}=#{escape_uri(mn)}\">#{mn}</a></td></tr>"
end
output <<= '</table>'
return(output)
end
def format_class_methods(obj = Object, method = methods, name = 'Methods')
output = ''
m = []
comment = ''
if method == 'constants'
if obj.type == 'Class' && obj.superclass
m = obj.send(method) - obj.superclass.send(method)
comment = '<i>super class constants ommited</i>'
elsif obj.type.to_s == 'Module'
begin
m = obj.send(method)
rescue NameError
comment <<= $!
end
else
m.push(obj.type.to_s)
end
else
m = obj.send(method)
end
output <<= "<h3>#{name}:</h3>"
output <<= comment
output <<= '<table border="1">'
len = output.length
m.sort.each do |m|
output <<= "<tr><td><code>#{escape_html(m)}</code></td>"
if method == 'constants'
output <<= "<td>#{escape_html(obj.const_get(m).inspect)}</td>"
else
output <<= "</tr>"
end
end
if len == output.length
output <<= "<tr><td>No #{name}</td></tr>"
end
output <<= '</table>'
return(output)
end
def get_classes()
class_types = []
ObjectSpace.each_object(Class) { |o|
class_types.push(o)
}
return(class_types)
end
def get_modules()
module_types = []
ObjectSpace.each_object(Module) { |o|
module_types.push(o)
}
return(module_types)
end
def get_params (r)
params = Hash.new([])
args = r.args
if args
args.split(/[&;]/n).each do |pairs|
key, value = pairs.split('=',2).collect{|v| unescape_uri(v) }
if params.has_key?(key)
params[key].push(value)
else
params[key] = [value]
end
end
end
return(params)
end
def inspect_class(class_name, classes)
output = ''
class_obj = nil
classes.each do |c|
class_obj = c.dup if class_name.to_s == c.to_s
end
output <<= "<h1>Class: <code>#{class_obj.to_s}</code></h1>"
klass = class_obj
hier = []
begin
hier.unshift("<code><a href=\"#{Apache.request.uri}?class=#{escape_uri(klass.to_s)}\">" + escape_html(klass.to_s) + '</a></code>')
klass = klass.superclass
end while klass
output <<= "Ancestry: " + hier.join(' > ') + "<br>"
output <<= 'Included Modules: '
im = []
class_obj.included_modules.sort.each do |m|
unless m
raise RuntimeError, m.inspect
end
im.push("<code><a href=\"#{Apache.request.uri}?module=#{m}\">#{m}</a></code>")
end
output <<= im.sort.join(', ') + '<br>'
output <<= "Class Variables: " + class_obj.class_variables.sort.join(',) + "<br>"
output <<= format_class_methods(class_obj, 'public_instance_methods', 'Public Instance Methods')
output <<= format_class_methods(class_obj, 'protected_instance_methods', 'Protected Instance Methods')
output <<= format_class_methods(class_obj, 'private_instance_methods', 'Private Instance Methods')
output <<= format_class_methods(class_obj, 'singleton_methods', 'Singleton Methods')
output <<= format_class_methods(class_obj, 'constants', 'Constants')
return(output)
end
def inspect_module(module_name, modules)
output = ''
module_obj = nil
modules.each do |m|
module_obj = m.dup if module_name.to_s == m.to_s
end
output <<= "<h1>Module: <code>#{module_obj.to_s}</code></h1>"
output <<= 'Included Modules: '
im = []
module_obj.included_modules.sort.each do |m|
unless m
raise RuntimeError, m.inspect
end
im.push("<code><a href=\"#{Apache.request.uri}?module=#{m}\">#{m}</a></code>")
end
output <<= im.sort.join(', ') + '<br>'
output <<= "Class Variables: " + module_obj.class_variables.sort.join(', ') + "<br>"
output <<= format_class_methods(module_obj, 'public_instance_methods', 'Public Instance Methods')
output <<= format_class_methods(module_obj, 'protected_instance_methods', 'Protected Instance Methods')
output <<= format_class_methods(module_obj, 'private_instance_methods',Private Instance Methods')
output <<= format_class_methods(module_obj, 'singleton_methods', 'Singleton Methods')
output <<= format_class_methods(module_obj, 'constants', 'Constants')
return(output)
end
def main (r)
r.content_type = 'text/html'
r.send_http_header()
return(Apache::OK) if r.header_only?
body(r)
end
def unescape_uri(string)
string.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/n) do
[$1.delete('%')].pack('H*')
end
end
main(r)
--YhFoJY/gx7awiIuK--
--T4IYkFBVPN84tP7K
Content-Type: application/pgp-signature
Content-Disposition: inline
-----BEGIN PGP SIGNATURE-----
Comment: Sean Chittenden <sean / chittenden.org>
iEYEARECAAYFAjuJs4cACgkQn09c7x7d+q2RGwCdGMl1XIyRlMTaG7Gmr79oLLl/
YusAn2U+/BxlK5/Vza355FMJVYk8a2vo
gN
-----END PGP SIGNATURE-----
--T4IYkFBVPN84tP7K--