Thursday, August 18, 2011

Debugging Consoles with Ruby

In ruby the debugger is not nearly as nifty as the console. Fortunately, there is https://github.com/pry/pry, a gem that provides an embeddable console.  In the simplest terms, Pry provides real-time access to your program's state through a Read-Eval-Print-Loop, much like Rails' console.

I've been a shell programmer for most of my working life, but I've never, ever, ever, been a fan of REPL user interfaces. They suck.  Readline interfaces are fine for shell tools, but there's no particular reason the user interface has to be line-oriented.

One of my first computers, an Atari 130XE, had an interesting editing interface for prototyping code.  It kept lines in a buffer, and supported both immediate execution (of un-numberd lines) and editing (of numbered lines).  Buffering, baby, buffering!  That's the difference between a 30 year old 8k BASIC console and a modern Ruby console: in-place editing.

But wait -- we can get a first approximation of in-place editing by cleverly hooking in an editor component. A quick search turned up two possibilities:  http://sketches.rubyforge.org/  and  https://github.com/jberkel/interactive_editor . I gave the interactive_editor gem a try.

To summarize, in a Rails 3.x app, you would just add the two gems to your Gemfile, run bundle, and then embed the expression

binding.pry

in your code where you want the console to open.

There are a few other details. The vimcast has some useful tips on setting up the interactive_editor, for instance, to make sure you get nice colorization turned on. But after that, using it is a breeze. Just use

vi

to open a vim editor into a temporary buffer. When you save and close, the console will run your code. Running vi again will reopen the last temporary file. It's a VEPL,  a Vim-Eval-Print-Loop.

But even more interesting for debugging, you can use the editor to work with objects through YAML representations.  Just add ".vi" to the end of an object, and your vim editor will open with the YAML. For instance, in UserController#update, I might do:

@user.vi

You get something like this:

  1 --- !ruby/object:User                                                                                                                                                             
  2 attributes:
  3   id: 2
  4   email: mitch.amiano@agilemarkup.com
  5   encrypted_password: $2a$10$s/NKiMEC1UfHzgG5JlCCJuHpZbAZ77dz623rq6gt12YUqW7RpvoWW
  6   reset_password_token:
  7   remember_token:

and so on (except, nicely colorized if you followed the vimcast). 

Not only is it much easier to look at and inspect than a puts or the debugger's "p" output, but the YAML is a mutable representation. Editing it, saving and closing will modify the in-memory object. You could do this sort of hot debugging already, but the editor makes it a lot easier to visualize, and lets you tweak multiple properties in one step without having to type any code.


Post a Comment