Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > [QUIZ] Object Browser (#8)

Reply
Thread Tools

[QUIZ] Object Browser (#8)

 
 
Ruby Quiz
Guest
Posts: n/a
 
      11-19-2004
The three rules of Ruby Quiz:

1. Please do not post any solutions or spoiler discussion for this quiz until
48 hours have passed from the time on this message.

2. Support Ruby Quiz by submitting ideas as often as you can:

http://www.grayproductions.net/ruby_quiz/

3. Enjoy!

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

by Jim Menard

Recently on ruby-talk, itsme123 asked if there was a generic object browser that
will "interactively browse a graph of connected objects by showing their
instance variables and letting me click through to browse".

The quiz challenge: write such a browser. It should be able to start at any
object or, if none is given to it, start at the main object ("self" at the top
level of any Ruby script).

The interface to the browser can be text-based or graphical.

I'm thinking of something like the Squeak Explorer (the new inspector). It's a
window that displays the object with an open/close triangle next to it. Click
the triangle, and the ivars are exposed.

V root: an OrderedCollection(a MyClass, a Number)
V 1: a MyClass
> name: 'the name'
> anotherIvar: 42
> 2: a Number


That's just one possible UI, of course.

Bonus points for allowing modification of instance variable values and for
allowing inspection of classes (remember, classes are objects, too!).


 
Reply With Quote
 
 
 
 
R. Mark Volkmann
Guest
Posts: n/a
 
      11-22-2004
I'm new to using gems. Can you tell me the command I need to run to get
ruby-gtk2 so I can run your code?

----- Original Message -----
From: "Jamis Buck" <>
To: "ruby-talk ML" <ruby->
Sent: Sunday, November 21, 2004 6:48 PM
Subject: [SOLUTION] Object Browser (#


> Well, I was kind of waiting to see what other people came up with, but
> since the list seems quiet on this topic, I guess I'll go ahead and post
> first.
>
> This is a VERY rough implementation. It uses ruby-gtk2, and is one of my
> first projects using that interface, so I've doubtless done all kinds of
> things wrong. But it works.
>
> By default, it displays the "main" object. You can see the class,
> superclass, instance/class variables, public/private/protected methods,
> and constants (where any of them apply and are non-empty).
>
> I wanted to add the ability to modify values, but didn't quite have time
> to get that far.
>
> This was a great quiz, though. I'd love to see a more sophisticated
> version of this. I can use mine, for instance, to do a kind of
> breakpoint in my code:
>
> ObjectBrowser.browse( @foo )
>
> And the program will stop, display the window, and wait for the window
> to close before proceeding.
>
> Anyway. Comments?
>
> - Jamis
>
> --
> Jamis Buck
>
> http://www.jamisbuck.org/jamis
>



--------------------------------------------------------------------------------


> require 'gtk2'
>
> DEFAULT_OBJECTBROWSER_ROOT = self
>
> class Object
> alias re_objbrowser_inspect :inspect
> def inspect
> result = pre_objbrowser_inspect
> result = $1 + " ...>" if result =~ /^(#<.*?:0x\w+) /
> result
> end
> end
>
> module ObjectBrowser
>
> def browse( root = DEFAULT_OBJECTBROWSER_ROOT )
> Interface.new( root ).display_and_wait
> end
> module_function :browse
>
> class Interface
> def initialize( root = DEFAULT_OBJECTBROWSER_ROOT )
> @root = root
> Gtk.init
> end
>
> def display
> window = Window.new( @root )
> window.show_all
> end
>
> def display_and_wait
> display
> wait
> end
>
> def wait
> Gtk.main
> end
> end
>
> class Window < Gtk::Window
> OBJECT = 1
> CLASS = 2
> INSTANCE_VARS = 3
> PUBLIC_METHODS = 4
> PROTECTED_METHODS = 5
> PRIVATE_METHODS = 6
> CLASS_VARS = 7
> CONSTANTS = 8
> SUPERCLASS = 9
> STRING = 10
> INSTANCE_METHODS = 11
>
> LABEL = 0
> TYPE = 1
> REF = 2
>
> def initialize( root )
> super( Gtk::Window::TOPLEVEL )
>
> signal_connect "delete_event", &method( n_delete )
> signal_connect "destroy", &method( n_destroy )
>
> vbox = Gtk::VBox.new
> add(vbox)
>
> pane = Gtk::VPaned.new
> vbox.add pane
>
> sw = Gtk::ScrolledWindow.new
> sw.set_policy *[Gtk:OLICY_AUTOMATIC]*2
> sw.shadow_type = Gtk::SHADOW_IN
> pane.add sw
>
> @model = Gtk::TreeStore.new( String, Integer, Integer )
> add_node( nil, root )
>
> @tree = Gtk::TreeView.new( @model )
> @tree.set_size_request -1, 400
>
> renderer = Gtk::CellRendererText.new
>
> col = Gtk::TreeViewColumn.new( "Data", renderer )
> col.set_cell_data_func renderer, &method( n_cell_render )
>
> @tree.append_column col
> @tree.expand_row Gtk::TreePath.new( "0" ), false
>
> @tree.signal_connect "row_expanded", &method( n_row_expanded )
>
> sw.add @tree
>
> sw = Gtk::ScrolledWindow.new
> sw.set_policy *[Gtk:OLICY_AUTOMATIC]*2
> sw.shadow_type = Gtk::SHADOW_IN
> pane.add sw
>
> @text = Gtk::TextView.new
> sw.add @text
>
> set_default_size 650, 500
> end
>
> def on_delete( widget, event )
> false
> end
>
> def on_destroy( widget )
> Gtk.main_quit
> end
>
> def on_cell_render( c, r, m, i )
> case i[TYPE]
> when OBJECT
> obj = ObjectSpace._id2ref( i[REF].to_i )
> r.text = "#{i[LABEL]}#{obj.inspect}"
> when CLASS, SUPERCLASS
> obj = ObjectSpace._id2ref( i[REF].to_i )
> r.text = "#{i[LABEL]} #{obj.name}"
> else
> r.text = i[LABEL]
> end
> end
>
> def on_row_expanded( widget, iter, path )
> unless iter.first_child[LABEL]
> case iter[1]
> when OBJECT, CLASS, SUPERCLASS then
> obj = ObjectSpace._id2ref( iter[REF].to_i )
> add_node iter, obj, iter.first_child
> when INSTANCE_VARS then
> obj = ObjectSpace._id2ref( iter.parent[REF].to_i )
> initialize_vars_list( obj, iter, obj.instance_variables.sort,
> :instance_variable_get )
> when PUBLIC_METHODS then
> obj = ObjectSpace._id2ref( iter.parent[REF].to_i )
> initialize_methods_list( obj, iter,
> obj.public_methods(false).sort )
> when PROTECTED_METHODS then
> obj = ObjectSpace._id2ref( iter.parent[REF].to_i )
> initialize_methods_list( obj, iter,
> obj.protected_methods(false).sort )
> when PRIVATE_METHODS then
> obj = ObjectSpace._id2ref( iter.parent[REF].to_i )
> initialize_methods_list( obj, iter,
> obj.private_methods(false).sort )
> when INSTANCE_METHODS then
> obj = ObjectSpace._id2ref( iter.parent[REF].to_i )
> initialize_methods_list( obj, iter,
> obj.instance_methods(false).sort, true )
> when CLASS_VARS then
> obj = ObjectSpace._id2ref( iter.parent[REF].to_i )
> initialize_vars_list( obj, iter,
> obj.class_variables.sort, :class_eval )
> when CONSTANTS then
> obj = ObjectSpace._id2ref( iter.parent[REF].to_i )
> constants = obj.constants
> if obj.respond_to?(:superclass) && obj.superclass
> constants = constants - obj.superclass.constants
> end
> initialize_vars_list( obj, iter, constants.sort, :const_get )
> else
> raise "don't know what to do with row of type #{iter[TYPE]}"
> end
> end
>
> path_str = iter.path.to_s + ":" + ( iter.n_children - 1 ).to_s
> path = Gtk::TreePath.new( path_str )
>
> @tree.scroll_to_cell( path, nil, true, 1.0, 0 )
> end
>
> def add_node( parent, object, node=nil )
> unless node
> node = add_row( parent, "", object, OBJECT, false )
> add_row( node, "class", object.class, CLASS )
> else
> add_row( parent, "class", object.class, CLASS, true, node )
> node = parent
> end
>
> if object.is_a?( Module )
> if object.respond_to?(:superclass) && object.superclass
> add_row( node, "extends", object.superclass, SUPERCLASS )
> end
> add_row_unless_empty(
> object.class_variables, node, "Class Variables", CLASS_VARS )
>
> constants = object.constants
> if object.respond_to?(:superclass) && object.superclass
> constants = constants - object.superclass.constants
> end
>
> add_row_unless_empty( constants, node, "Constants", CONSTANTS )
> add_row_unless_empty( object.instance_methods(false), node,
> "Instance Methods", INSTANCE_METHODS )
> end
>
> add_row_unless_empty( object.instance_variables, node,
> "Instance Variables", INSTANCE_VARS )
> add_row_unless_empty( object.public_methods(false), node,
> "Public Methods", PUBLIC_METHODS )
> add_row_unless_empty( object.protected_methods(false), node,
> "Protected Methods", PROTECTED_METHODS )
> add_row_unless_empty( object.private_methods(false), node,
> "Private Methods", PRIVATE_METHODS )
>
> node
> end
>
> def add_row_unless_empty( list, node, name, type, add_empty=true )
> unless list.empty?
> summary = list.sort.join( "," )
> summary = summary[0,60] + "..." if summary.length > 63
> add_row( node, "#{name} (#{summary})", nil, type )
> end
> end
>
> def add_row( parent, label, value, type, add_empty=true, node=nil )
> node = @model.append( parent ) unless node
>
> node[ LABEL ] = label
> node[ TYPE ] = type
> node[ REF ] = value.object_id
>
> @model.append( node ) if add_empty
>
> node
> end
>
> def initialize_methods_list( obj, iter, list, instance=false )
> node = iter.first_child
> list.each do |item|
> if instance
> method = obj.instance_method( item.to_sym )
> else
> method = obj.method( item.to_sym )
> end
> add_row iter, item + "(#{method.arity})", obj, STRING, false, node
> node = nil
> end
> end
>
> def initialize_vars_list( obj, iter, list, message )
> node = iter.first_child
> list.each do |item|
> value = obj.__send__( message, item )
> add_row iter, "#{item}=", value, OBJECT, true, node
> node = nil
> end
> end
> end
>
> end
>
> if __FILE__ == $0
> @obj = ObjectBrowser::Interface.new
> @obj.display_and_wait
> end
>





 
Reply With Quote
 
 
 
 
Masao Mutoh
Guest
Posts: n/a
 
      11-22-2004
Hi,

On Mon, 22 Nov 2004 11:38:36 +0900
Jamis Buck <> wrote:

> R. Mark Volkmann wrote:
> > I'm new to using gems. Can you tell me the command I need to run to get
> > ruby-gtk2 so I can run your code?

>
> Unfortunately, ruby-gtk2 is not a gem, nor is it in rpa. So you have to
> install it the "hard" way--from source. If you're on Windows, it's even
> harder: you have to install GTK2 first.
>
> GTK2: http://www.gtk.org
> Ruby-GTK2 (part of Ruby-Gnome2): http://ruby-gnome2.sourceforge.jp/
>
> Having never used GTK in Windows, I have no idea how easy/hard it is to
> get ruby-gtk2 running under Windows. YMMV. YHBW.


See http://ruby-gnome2.sourceforge.jp/hi...de+for+Windows
You can install them just four steps, though it's not one click .

> - Jamis
>
> P.S.: A plea to the ruby-gnome2 folks: a gemmable version would be a
> real boon. A similar plea to the RPA folks...


Good idea. Are there anyone to work for them ?

--
:% Masao Mutoh<>


 
Reply With Quote
 
James Edward Gray II
Guest
Posts: n/a
 
      11-22-2004
On Nov 21, 2004, at 6:48 PM, Jamis Buck wrote:

> Well, I was kind of waiting to see what other people came up with, but
> since the list seems quiet on this topic, I guess I'll go ahead and
> post first.


[snip description]

> Anyway. Comments?


Yes. Would you mind posting a few screenshots, for those of us having
trouble getting past the interface requirements?

James Edward Gray II



 
Reply With Quote
 
Masao Mutoh
Guest
Posts: n/a
 
      11-22-2004
Hi Lothar,

On Tue, 23 Nov 2004 00:07:38 +0900
Lothar Scholz <> wrote:

> Hello Masao,
>
> MM> Hi,
>
> MM> On Mon, 22 Nov 2004 11:38:36 +0900
> MM> Jamis Buck <> wrote:
>
>
> MM> See
> MM> http://ruby-gnome2.sourceforge.jp/hi...de+for+Windows
> MM> You can install them just four steps, though it's not one click .
>
> And fails on step 2 with
>
> Z:\work\arachno\make>ruby -e "require 'gtk2'"
> c:/ruby/lib/ruby/site_ruby/1.8/i386-msvcrt/glib2.so: 126: The specified module could not be found.
> - c:/ruby/lib/ruby/site_ruby/1.8/i386-msvcrt/glib2.so (LoadError)
> from c:/ruby/lib/ruby/site_ruby/1.8/glib2.rb:64
> from c:/ruby/lib/ruby/site_ruby/1.8/gtk2.rb:1:in `require'
> from c:/ruby/lib/ruby/site_ruby/1.8/gtk2.rb:1
> from -e:1:in `require'
> from -e:1
>
> The file exists all all DLL's also, so there is some other thing wrong here.
> My System is WinXP SP2.



On step 2? Did you do step 3 and 4?

And are there c:/ruby/lib/ruby/site_ruby/1.8/i386-msvcrt/glib2.so ?


--
:% Masao Mutoh<>


 
Reply With Quote
 
Mauricio Fernández
Guest
Posts: n/a
 
      11-22-2004
On Mon, Nov 22, 2004 at 10:55:35PM +0900, Masao Mutoh wrote:
> See http://ruby-gnome2.sourceforge.jp/hi...de+for+Windows
> You can install them just four steps, though it's not one click .
>
> > - Jamis
> >
> > P.S.: A plea to the ruby-gnome2 folks: a gemmable version would be a
> > real boon. A similar plea to the RPA folks...

>
> Good idea. Are there anyone to work for them ?


The RPA stuff is on the way (will take a while though).

--
Hassle-free packages for Ruby?
RPA is available from http://www.rubyarchive.org/


 
Reply With Quote
 
Masao Mutoh
Guest
Posts: n/a
 
      11-22-2004
Hi,

On Tue, 23 Nov 2004 00:50:47 +0900
Lothar Scholz <> wrote:

> Hello Masao,
>
>
> MM> On step 2? Did you do step 3 and 4?
>
> Yes.
>
> MM> And are there
> MM> c:/ruby/lib/ruby/site_ruby/1.8/i386-msvcrt/glib2.so ?
>
> Yes.


Hmm. What versions are the One click installer and GTK ?
Could you try the same versions of the information page?

In my environment(WinXP SP2), it works.

Are there anyone to test it?

--
:% Masao Mutoh<>


 
Reply With Quote
 
Masao Mutoh
Guest
Posts: n/a
 
      11-22-2004
Hi,

On Tue, 23 Nov 2004 00:51:28 +0900
Mauricio Fern__ndez <> wrote:

> On Mon, Nov 22, 2004 at 10:55:35PM +0900, Masao Mutoh wrote:
> > See http://ruby-gnome2.sourceforge.jp/hi...de+for+Windows
> > You can install them just four steps, though it's not one click .
> >
> > > - Jamis
> > >
> > > P.S.: A plea to the ruby-gnome2 folks: a gemmable version would be a
> > > real boon. A similar plea to the RPA folks...

> >
> > Good idea. Are there anyone to work for them ?

>
> The RPA stuff is on the way (will take a while though).


Wow, Great .
Thanks in advance.

--
:% Masao Mutoh<>


 
Reply With Quote
 
Masao Mutoh
Guest
Posts: n/a
 
      11-22-2004
Hi,

On Tue, 23 Nov 2004 01:28:28 +0900
Jamis Buck <> wrote:

> Masao Mutoh wrote:
> > Hi,
> >
> > On Tue, 23 Nov 2004 00:50:47 +0900
> > Lothar Scholz <> wrote:
> >
> >
> >>Hello Masao,
> >>
> >>
> >>MM> On step 2? Did you do step 3 and 4?
> >>
> >>Yes.
> >>
> >>MM> And are there
> >>MM> c:/ruby/lib/ruby/site_ruby/1.8/i386-msvcrt/glib2.so ?
> >>
> >>Yes.

> >
> >
> > Hmm. What versions are the One click installer and GTK ?
> > Could you try the same versions of the information page?
> >
> > In my environment(WinXP SP2), it works.
> >
> > Are there anyone to test it?
> >

>
> I just tried it (thank-you, VMWare!), and it worked flawlessly. I'm also
> using WinXP SP2, with Ruby 1.8.2. I grabbed the recommended packages
> from each step.


Thanks.

Lothar, check your environment carefully again, please.
I recommand to uninstall ruby, ruby-gtk2 and gtk2 once, then re-install them
with latest versions of them.

--
:% Masao Mutoh<>


 
Reply With Quote
 
Brian Schröder
Guest
Posts: n/a
 
      11-23-2004
Hello Group,

Thanks for the quiz. I always wanted to learn more about the reflection capabilites of ruby, and indeed there is quite a lot to learn. This quiz was not too complicated, but the design of a good gui takes a lot of time. (Especially if you're not accustomed to the toolkit).

I implemented a gnome2/gtk version. I did not use code from the other solution, but the next step will be to see what I can borrow.

I submit now, because I've already invested too much time. The code is not beautifull and could need a heavy facelift.

The difference to the other solution is, that I'm starting with a class-tree from which you can get to all the objects. I think the right pane in my solution is more or less what was specified in the quiz.

You can see the code and screenshots at:

http://ruby.brian-schroeder.de/quiz/object_browser/

Regards,

Brian

--
Brian Schröder
http://www.brian-schroeder.de/



 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Try this Latest Firefox browser at http://browser.friendsrus.net subs2me@gmail.com Firefox 9 12-28-2005 09:20 AM
Object creation - Do we really need to create a parent for a derieved object - can't the base object just point to an already created base object jon wayne C++ 9 09-22-2005 02:06 AM
Re: Browser plug-in to interact with browser DKM Java 15 06-12-2005 02:11 AM
Browser information not being sent to the Domain Master Browser Russell Stamper Cisco 1 10-12-2004 08:14 PM
Browser levels, PDAs and browser sniffing Lauchlan M ASP .Net 2 08-17-2003 04:58 PM



Advertisments