Sunday, September 18, 2005

Mainstream languages: you may now bow to Ruby.

require 'rubygems'
require 'binding_of_caller'
module Kernel
  def debug
    Binding.of_caller do |b|
      var_types = ['local','instance','self.class.class'] #,'global']
      var_types.each do |var_type|
        puts "#{var_type.split('.')[-1].capitalize} variables:"
        eval(var_type+"_variables",b).each do |var|
          puts "#{var} = #{(eval var,b).inspect}" unless var =~ /gempath_searcher/
        end
      end
    end
  end
end
Perfect for script/breakpointer in a Rails app.

9 Comments:

At 7:12 AM, Blogger flgr said...

Nice work. In the future there will also be a frontend that shows that kind of stuff automatically:

http://flgr.0x42.net/breakpoint/cyclic-threads.png

It still needs some work to make things polished, but I hope to have this ready soon.

 
At 4:25 PM, Blogger Devin said...

1. Thanks. I realized this morning that it doesn't actually work in Rails' script/breakpointer. Apparently, the drb magic that goes on swallows stdout and stderr whole. I made a workaround to look for RAILS_ROOT and if defined?, use RAILS_DEFAULT_LOGGER instead, but I don't like it, since you have to be tailing development.log in another term. I might crack into the script/breakpointer mojo to fix it correctly (if possible), and so I may learn more about it.

2. Like, sweet. I continue to be outdone by, like, orders of orders of magnitude. This is a good thing for me, since it's all open source. :)

3. How did you find my blog?

 
At 4:37 PM, Blogger flgr said...

1. Use client.puts instead of puts. It will output stuff to the breakpoint client's STDOUT instead of the server's. I'm not sure if client() also works with local breakpoints, but if you can confirm it doesn't I will change it.

2. Heh, it isn't even out yet. ;)

3. Technorati. I have a search for mentions of myself or my projects. It is nice for quickly giving and receiving feedback. ;)

 
At 5:23 PM, Blogger Devin said...

Hehe. I'm causing it to do some pretty funky things. A sign that I'm acting pretty cluelessly.

irb(#<TodoController:0x265fba8>):030:0> PP::pp [1,2,3],client
SyntaxError: (eval):7: compile error
(eval):2: syntax error
result = lambda { |block, *args| <<(*args, &block) }
^
(eval):2: syntax error
result = lambda { |block, *args| <<(*args, &block) }
^
from (druby://devin-mullins-powerbook-g4-15.local:49413) /opt/local/lib/ruby/gems/1.8/gems/rails-0.13.1/lib/breakpoint_client.rb:98:in `eval'
from (druby://localhost:42531) /opt/local/lib/ruby/gems/1.8/gems/rails-0.13.1/lib/breakpoint.rb:136:in `eval'
from (druby://localhost:42531) /opt/local/lib/ruby/gems/1.8/gems/rails-0.13.1/lib/breakpoint.rb:155:in `method_missing'
from (druby://localhost:42531) /opt/local/lib/ruby/1.8/prettyprint.rb:187:in `text'
from (druby://localhost:42531) /opt/local/lib/ruby/1.8/prettyprint.rb:221:in `group'
from (druby://localhost:42531) /opt/local/lib/ruby/1.8/pp.rb:211:in `pp'
from (druby://localhost:42531) /opt/local/lib/ruby/1.8/pp.rb:165:in `pp'
from (druby://localhost:42531) /opt/local/lib/ruby/1.8/pp.rb:165:in `guard_inspect_key'
from (druby://localhost:42531) /opt/local/lib/ruby/1.8/pp.rb:165:in `pp'
from (druby://localhost:42531) (irb):30:in `index'

Also, it seems I'm pushing the limits of Blogger's comment system. I need to get a code-friendly blog.

 
At 5:25 PM, Blogger Devin said...

Yeah, I should check out the code. It seems client is not a real object a-tall. :)

 
At 5:31 PM, Blogger Devin said...

OK, this line causes breakpoint to flip out:

PP::pp(eval(var,b), ret)

(ret is a String.)

The error message is:

ArgumentError: wrong number of arguments (1 for 0)
from (druby://localhost:42531) /opt/local/lib/ruby/1.8/pp.rb:289:in `method'

which, judging by the source code at that line, is a pretty insane error to throw.

 
At 7:51 AM, Blogger flgr said...

Well, either do client.puts(obj) or client.STDOUT.puts(obj) or PP.pp(obj, client.STDOUT) or similar.

client() returns a real object, but it is a proxy object that just forwards method calls on it over the network to the client's toplevel binding.

Oh, and you discovered a real bug: client << 5 would fail with a syntax error -- this has been fixed and it will correctly fail with a NoMethodError in the next release. Thanks for discovering this.

 
At 7:54 AM, Blogger flgr said...

Oh, and I'm not sure what's happening with PP::pp(eval(var,b), ret) -- what's the result of eval(var, b)? What's ret?

AFAIK I don't override method() anywhere in ruby-breakpoint -- it could be something that Rails or another library does. More data would help here. Thanks!

 
At 3:44 PM, Blogger Devin said...

OK. Code posted here.

Take that, put it somewhere. Generate a blank rails app, generate a controller. Stick a def index; raise StandardError end in there.

Hit the page, click "Retry with Breakpoint", popup script/breakpointer, and type require 'thatfunkyscript'; vars in there.

Yeah, the script could use improvement in several other ways, too. It was something I churned out initially (on the blog post) in a coupla minutes. It looks like you'll be providing the much-awesomer interface, rendering exactness on this unnecessary. :) Still, glad to help out with the breakpoint madness.

 

Post a Comment

<< Home