--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. =20
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

--=20
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 PURPO=
SE
#  ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
#  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTI=
AL
#  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, STRI=
CT
#  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 =3D Apache.request

def body (r)
  params =3D 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(/&/, '&amp;').gsub(/\"/, '&quot;').gsub(/</, '&lt;').gsub(/>/, '=
&gt;')
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 =3D 'Modules', uriname =3D 'module')
  output =3D ''
  ordered_modules =3D []
  module_list.each do |ml|
    ordered_modules.push(ml.to_s)
  end

  output <<=3D "<h1>#{title}:</h1>"
  output <<=3D '<table border=3D"1">'
  ordered_modules.uniq.sort.each do |mn|
    output <<=3D "<tr><td><a href=3D\"#{Apache.request.uri}?#{uriname}=3D#{=
escape_uri(mn)}\">#{mn}</a></td></tr>"
  end

  output <<=3D '</table>'
  return(output)
end



def format_class_methods(obj =3D Object, method =3D methods, name =3D 'Meth=
ods')
  output =3D ''
  m =3D []
  comment =3D ''

  if method =3D=3D 'constants'
    if obj.type =3D=3D 'Class' && obj.superclass
      m =3D obj.send(method) - obj.superclass.send(method)
      comment =3D '<i>super class constants ommited</i>'
    elsif obj.type.to_s =3D=3D 'Module'
      begin
	m =3D obj.send(method)
      rescue NameError
	comment <<=3D $!
      end
    else
      m.push(obj.type.to_s)
    end
  else
    m =3D obj.send(method)
  end

  output <<=3D "<h3>#{name}:</h3>"
  output <<=3D comment
  output <<=3D '<table border=3D"1">'

  len =3D output.length
  m.sort.each do |m|
    output <<=3D "<tr><td><code>#{escape_html(m)}</code></td>"

    if method =3D=3D 'constants'
      output <<=3D "<td>#{escape_html(obj.const_get(m).inspect)}</td>"
    else
      output <<=3D "</tr>"
    end
  end

  if len =3D=3D output.length
    output <<=3D "<tr><td>No #{name}</td></tr>"
  end
  output <<=3D '</table>'

  return(output)
end



def get_classes()
  class_types =3D []
  ObjectSpace.each_object(Class) { |o|
    class_types.push(o)
  }

  return(class_types)
end



def get_modules()
  module_types =3D []
  ObjectSpace.each_object(Module) { |o|
    module_types.push(o)
  }

  return(module_types)
end



def get_params (r)
  params =3D Hash.new([])
  args =3D r.args

  if args
    args.split(/[&;]/n).each do |pairs|
      key, value =3D pairs.split('=3D',2).collect{|v| unescape_uri(v) }
      if params.has_key?(key)
	params[key].push(value)
      else
	params[key] =3D [value]
      end
    end
  end

  return(params)
end



def inspect_class(class_name, classes)
  output =3D ''
  class_obj =3D nil

  classes.each do |c|
    class_obj =3D c.dup if class_name.to_s =3D=3D c.to_s
  end

  output <<=3D "<h1>Class: <code>#{class_obj.to_s}</code></h1>"

  klass =3D class_obj
  hier =3D []
  begin
    hier.unshift("<code><a href=3D\"#{Apache.request.uri}?class=3D#{escape_=
uri(klass.to_s)}\">" + escape_html(klass.to_s) + '</a></code>')
    klass =3D klass.superclass
  end while klass


  output <<=3D "Ancestry: " + hier.join('&nbsp;>&nbsp;') + "<br>"


  output <<=3D 'Included Modules: '
  im =3D []
  class_obj.included_modules.sort.each do |m|
    unless m
      raise RuntimeError, m.inspect
    end
     =20
    im.push("<code><a href=3D\"#{Apache.request.uri}?module=3D#{m}\">#{m}</=
a></code>")
  end
  output <<=3D im.sort.join(', ') + '<br>'

  output <<=3D "Class Variables: " + class_obj.class_variables.sort.join(',=
 ') + "<br>"


  output <<=3D format_class_methods(class_obj, 'public_instance_methods', '=
Public Instance Methods')
  output <<=3D format_class_methods(class_obj, 'protected_instance_methods'=
, 'Protected Instance Methods')
  output <<=3D format_class_methods(class_obj, 'private_instance_methods', =
'Private Instance Methods')
  output <<=3D format_class_methods(class_obj, 'singleton_methods', 'Single=
ton Methods')
  output <<=3D format_class_methods(class_obj, 'constants', 'Constants')

  return(output)
end



def inspect_module(module_name, modules)
  output =3D ''
  module_obj =3D nil

  modules.each do |m|
    module_obj =3D m.dup if module_name.to_s =3D=3D m.to_s
  end

  output <<=3D "<h1>Module: <code>#{module_obj.to_s}</code></h1>"

  output <<=3D 'Included Modules: '
  im =3D []
  module_obj.included_modules.sort.each do |m|
    unless m
      raise RuntimeError, m.inspect
    end
     =20
    im.push("<code><a href=3D\"#{Apache.request.uri}?module=3D#{m}\">#{m}</=
a></code>")
  end
  output <<=3D im.sort.join(', ') + '<br>'

  output <<=3D "Class Variables: " + module_obj.class_variables.sort.join('=
, ') + "<br>"


  output <<=3D format_class_methods(module_obj, 'public_instance_methods', =
'Public Instance Methods')
  output <<=3D format_class_methods(module_obj, 'protected_instance_methods=
', 'Protected Instance Methods')
  output <<=3D format_class_methods(module_obj, 'private_instance_methods',=
 'Private Instance Methods')
  output <<=3D format_class_methods(module_obj, 'singleton_methods', 'Singl=
eton Methods')
  output <<=3D format_class_methods(module_obj, 'constants', 'Constants')

  return(output)
end



def main (r)
  r.content_type =3D '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
=QpgN
-----END PGP SIGNATURE-----

--T4IYkFBVPN84tP7K--
	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. =20
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

--=20
Sean Chittenden
#!/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 PURPO=
SE
#  ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
#  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTI=
AL
#  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, STRI=
CT
#  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 =3D Apache.request

def body (r)
  params =3D 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(/&/, '&amp;').gsub(/\"/, '&quot;').gsub(/</, '&lt;').gsub(/>/, '=
&gt;')
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 =3D 'Modules', uriname =3D 'module')
  output =3D ''
  ordered_modules =3D []
  module_list.each do |ml|
    ordered_modules.push(ml.to_s)
  end

  output <<=3D "<h1>#{title}:</h1>"
  output <<=3D '<table border=3D"1">'
  ordered_modules.uniq.sort.each do |mn|
    output <<=3D "<tr><td><a href=3D\"#{Apache.request.uri}?#{uriname}=3D#{=
escape_uri(mn)}\">#{mn}</a></td></tr>"
  end

  output <<=3D '</table>'
  return(output)
end



def format_class_methods(obj =3D Object, method =3D methods, name =3D 'Meth=
ods')
  output =3D ''
  m =3D []
  comment =3D ''

  if method =3D=3D 'constants'
    if obj.type =3D=3D 'Class' && obj.superclass
      m =3D obj.send(method) - obj.superclass.send(method)
      comment =3D '<i>super class constants ommited</i>'
    elsif obj.type.to_s =3D=3D 'Module'
      begin
	m =3D obj.send(method)
      rescue NameError
	comment <<=3D $!
      end
    else
      m.push(obj.type.to_s)
    end
  else
    m =3D obj.send(method)
  end

  output <<=3D "<h3>#{name}:</h3>"
  output <<=3D comment
  output <<=3D '<table border=3D"1">'

  len =3D output.length
  m.sort.each do |m|
    output <<=3D "<tr><td><code>#{escape_html(m)}</code></td>"

    if method =3D=3D 'constants'
      output <<=3D "<td>#{escape_html(obj.const_get(m).inspect)}</td>"
    else
      output <<=3D "</tr>"
    end
  end

  if len =3D=3D output.length
    output <<=3D "<tr><td>No #{name}</td></tr>"
  end
  output <<=3D '</table>'

  return(output)
end



def get_classes()
  class_types =3D []
  ObjectSpace.each_object(Class) { |o|
    class_types.push(o)
  }

  return(class_types)
end



def get_modules()
  module_types =3D []
  ObjectSpace.each_object(Module) { |o|
    module_types.push(o)
  }

  return(module_types)
end



def get_params (r)
  params =3D Hash.new([])
  args =3D r.args

  if args
    args.split(/[&;]/n).each do |pairs|
      key, value =3D pairs.split('=3D',2).collect{|v| unescape_uri(v) }
      if params.has_key?(key)
	params[key].push(value)
      else
	params[key] =3D [value]
      end
    end
  end

  return(params)
end



def inspect_class(class_name, classes)
  output =3D ''
  class_obj =3D nil

  classes.each do |c|
    class_obj =3D c.dup if class_name.to_s =3D=3D c.to_s
  end

  output <<=3D "<h1>Class: <code>#{class_obj.to_s}</code></h1>"

  klass =3D class_obj
  hier =3D []
  begin
    hier.unshift("<code><a href=3D\"#{Apache.request.uri}?class=3D#{escape_=
uri(klass.to_s)}\">" + escape_html(klass.to_s) + '</a></code>')
    klass =3D klass.superclass
  end while klass


  output <<=3D "Ancestry: " + hier.join('&nbsp;>&nbsp;') + "<br>"


  output <<=3D 'Included Modules: '
  im =3D []
  class_obj.included_modules.sort.each do |m|
    unless m
      raise RuntimeError, m.inspect
    end
     =20
    im.push("<code><a href=3D\"#{Apache.request.uri}?module=3D#{m}\">#{m}</=
a></code>")
  end
  output <<=3D im.sort.join(', ') + '<br>'

  output <<=3D "Class Variables: " + class_obj.class_variables.sort.join(',=
 ') + "<br>"


  output <<=3D format_class_methods(class_obj, 'public_instance_methods', '=
Public Instance Methods')
  output <<=3D format_class_methods(class_obj, 'protected_instance_methods'=
, 'Protected Instance Methods')
  output <<=3D format_class_methods(class_obj, 'private_instance_methods', =
'Private Instance Methods')
  output <<=3D format_class_methods(class_obj, 'singleton_methods', 'Single=
ton Methods')
  output <<=3D format_class_methods(class_obj, 'constants', 'Constants')

  return(output)
end



def inspect_module(module_name, modules)
  output =3D ''
  module_obj =3D nil

  modules.each do |m|
    module_obj =3D m.dup if module_name.to_s =3D=3D m.to_s
  end

  output <<=3D "<h1>Module: <code>#{module_obj.to_s}</code></h1>"

  output <<=3D 'Included Modules: '
  im =3D []
  module_obj.included_modules.sort.each do |m|
    unless m
      raise RuntimeError, m.inspect
    end
     =20
    im.push("<code><a href=3D\"#{Apache.request.uri}?module=3D#{m}\">#{m}</=
a></code>")
  end
  output <<=3D im.sort.join(', ') + '<br>'

  output <<=3D "Class Variables: " + module_obj.class_variables.sort.join('=
, ') + "<br>"


  output <<=3D format_class_methods(module_obj, 'public_instance_methods', =
'Public Instance Methods')
  output <<=3D format_class_methods(module_obj, 'protected_instance_methods=
', 'Protected Instance Methods')
  output <<=3D format_class_methods(module_obj, 'private_instance_methods',=
 'Private Instance Methods')
  output <<=3D format_class_methods(module_obj, 'singleton_methods', 'Singl=
eton Methods')
  output <<=3D format_class_methods(module_obj, 'constants', 'Constants')

  return(output)
end



def main (r)
  r.content_type =3D '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)



-----BEGIN PGP SIGNATURE-----
Comment: Sean Chittenden <sean / chittenden.org>

iEYEARECAAYFAjuJs4cACgkQn09c7x7d+q2RGwCdGMl1XIyRlMTaG7Gmr79oLLl/
YusAn2U+/BxlK5/Vza355FMJVYk8a2vo
=QpgN
-----END PGP SIGNATURE-----