From: Sean Chittenden Date: 2001-08-27T11:42:22+09:00 Subject: [ruby-talk:20413] Interactive objectspace script... --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 # # Copyright 2001 # Sean Chittenden . 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 # 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 . 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(/&/, '&').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 =3D 'Modules', uriname =3D 'module') output =3D '' ordered_modules =3D [] module_list.each do |ml| ordered_modules.push(ml.to_s) end output <<=3D "

#{title}:

" output <<=3D '' ordered_modules.uniq.sort.each do |mn| output <<=3D "" end output <<=3D '
#{mn}
' 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 'super class constants ommited' 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 "

#{name}:

" output <<=3D comment output <<=3D '' len =3D output.length m.sort.each do |m| output <<=3D "" if method =3D=3D 'constants' output <<=3D "" else output <<=3D "" end end if len =3D=3D output.length output <<=3D "" end output <<=3D '
#{escape_html(m)}#{escape_html(obj.const_get(m).inspect)}
No #{name}
' 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 "

Class: #{class_obj.to_s}

" klass =3D class_obj hier =3D [] begin hier.unshift("" + escape_html(klass.to_s) + '') klass =3D klass.superclass end while klass output <<=3D "Ancestry: " + hier.join(' > ') + "
" output <<=3D 'Included Modules: ' im =3D [] class_obj.included_modules.sort.each do |m| unless m raise RuntimeError, m.inspect end =20 im.push("#{m}") end output <<=3D im.sort.join(', ') + '
' output <<=3D "Class Variables: " + class_obj.class_variables.sort.join(',= ') + "
" 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 "

Module: #{module_obj.to_s}

" output <<=3D 'Included Modules: ' im =3D [] module_obj.included_modules.sort.each do |m| unless m raise RuntimeError, m.inspect end =20 im.push("
#{m}") end output <<=3D im.sort.join(', ') + '
' output <<=3D "Class Variables: " + module_obj.class_variables.sort.join('= , ') + "
" 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 iEYEARECAAYFAjuJs4cACgkQn09c7x7d+q2RGwCdGMl1XIyRlMTaG7Gmr79oLLl/ YusAn2U+/BxlK5/Vza355FMJVYk8a2vo =QpgN -----END PGP SIGNATURE----- --T4IYkFBVPN84tP7K--