Posted on July 21, 2006
Scott Bronson has published a very cool article about the current offerings when it comes to debugging Ruby applications. First off, I appreciate the kind words regarding ruby-debug extension. Second off, he made a very interesting observation:
I hardly ever need a debugger when developing new Ruby on Rails applications.
However, when trying to understand an existing codebase, I find that few things
help more in understanding exactly what is going on than stepping through
the code using a debugger.
I fully subscribe to this idea. I've been developing with Ruby since 2002 and I hardly ever needed a debugger. But there were a couple of times when I really wanted to have a debugger. It was when I ran into a bug in an existing library and I didn't have an intimate knowledge of its internals (no pun intended). It's just much easier to step through the code and see how things are meshed together.
Also, I'd like to make some comments on the current debugger offerings:
There is an official debug.rb library bundled with the standard Ruby distribution. AFAIK, all other debuggers, except maybe Arachno Ruby's one, are based on this small and nifty library, including my ruby-debug. The major drawback of it is the speed of the execution.
Debugger from ZenHack tries to fix this problem by re-implementing trace function in C using RubyInline extension. Unfortunately, it is still quite slow to my taste.
Debugger from Arachno Ruby IDE is very nice, but the last time I checked it used a patched version of Ruby interpreter. Which means that you have to ask for a new patch with each subsequent Ruby release. (But don't quote me on that though :-)
There is another GUI debugger called MrGuid which uses a slightly modified version of debug.rb.
Filed under: Ruby ruby-debug |
0 comments
Posted on July 16, 2006
Remote Debugging
I've just released a new version of ruby-debug which has a new feature: remote debugging.
In order to use it you have to pass -s parameter to rdebug script:
$ rdebug -s <script.rb>
This option makes the debugger start listening for an incoming TCP connection on port 8989, by default. You can change the default port and host name with -p and -h option respectively.
Now when the debugger is started this way, you can connect to it using this command:
$ rdebug -c
Also since this feature is implemented using plain sockets, you can connect to the remote debugger using a plain telnet client:
$ telnet localhost 8989
Trying ::1...
Connected to localhost.
Escape character is '^]'.
script/../config/../app/controllers/shop_controller.rb:28: product_id = params['id']
PROMPT (rdb:3)
list
[23, 32] in script/../config/../app/controllers/shop_controller.rb
23 end
24 end
25
26 def product
27 debugger
=> 28 product_id = params['id']
29 unless product_id
30 redirect_to :action => 'index'
31 return
32 end
PROMPT (rdb:3)
cont
API Changes
One more thing. There are two important changes have been made.
First off, starting from this version when you require 'ruby-debug', it doesn't activate the debugger by default. You have to explicitly activate it by calling Debugger#start method. Also if you want to activate remote debugging, you should start the listener server by calling Debugger#start_server(host, port) method.
require 'ruby-debug'
Debugger.start_server
Debugger.start
Second off, it used to be possible at the debugger prompt to type anything and the debugger evaluates the expression, now you should use eval or p command.
Win32 gem
Thanks to Max Muermann, win32 version of ruby-debug 0.1.5 is available for download. The ruby-debug 0.2 version is coming too.
Update: win32 version of ruby-debug 0.2 is now available.
Filed under: Ruby ruby-debug |
3 comments
Posted on July 13, 2006
It's a quite common for an action to finish by sending a confirmation
email to the client. Usually you don't want to put this logic directly in your model. Models deal with a business rules and shouldn't care about emails or any other infrastructure nonsense (unless of cause this is the business domain of your application). In Rails you define your business logic in terms of ActiveRecord::Base and the delivery of emails in terms of ActionMailer::Base. In order to decouple these two, Rails provides a mechanism of ActiveRecord observers. These glue objects listen for changes in the model and react accordingly (usually using after_save method). If we need to perform a complex operation that involves updating several tables, it is better to wrap it with a database transaction. What I didn't pay attention to is that observer's after_save method is also a part of the transaction, meaning the transaction will remain open until this method finish.
This lead to a potential problem. What happens when your email server is under heavy load or you have some kind of DNS problem and the address resolution takes unusual amount of time? Your transactions will stay open for a long time and some of them will eventually time out.
Filed under: Rails |
3 comments
Posted on July 11, 2006
Preface
Overcomplicated specifications lead to overcomplicated implementations. Lately I've been fixing issues with ActionWebService framework - a soon to be removed part of Ruby on Rails. I have to use SOAP in the web application I'm developing. My client needs to keep his product inventory in a good shape and he requested to implement some of the inventory management functionality using handheld devices. There is a .Net environment available for this kind of devices and it works very well. So I desperately needed a functional web service implementation for Rails. That why I volunteered to fix AWS. And that's when I found out that ruby-breakpoint just doesn't cut it. Don't get me wrong, soap4r is a fine piece of software, but SOAP is difficult and obscure, which leads to complicated libraries that implement it. The situation is even worse when such libraries have almost no documentation whatsoever.
So instead of just stopping at some point in your program to examine the environment (the facility offered by ruby-breakpoint library), ruby-debug extension offers the full-fledged debugger for Ruby. The main difference between ruby-debug and the standard debug.rb library is the speed of the execution. Major problem with debug.rb is that it uses Kernel#set_trace_func method, which requires creation of Binding object for each hook invocation. It is fine for small scripts, but for the real world applications like Rails ones, debug.rb is almost impossible to use. You just sit and watch how Ruby interpreter creates enormous amount of Binding objects, just in order to destroy them with the immediate garbage collection cycle. It also explains that ruby-debug doesn't support watchpoints for the same reason.
Filed under: Rails Ruby ruby-debug |
Tagged with: debug ruby |
Posted on July 07, 2006
I've been watching a thread on ruby-talk about the possibility to have a faster debugger for Ruby.
Now when Ruby 1.8.4 has a better C based API for tracing code execution, it is possible to significantly speed up debug.rb. I've been playing with this idea for last two days and came up with ruby-debug extension:
Follow these easy steps:
Enjoy.
Update. I've created a project on rubyforge.org for this extension and uploaded a bugfix version 0.1.2. Now you don't have to download the gem file from this site. Just use
$ gem install ruby-debug
command to install it.
Filed under: Rails Ruby ruby-debug |