Posts Tagged ‘Rails’

Make ruby-debug work better

If you’ve written Ruby, chances are you’ve had to use ruby-debug. You might’ve thought the experience sucked — especially the fact that the debugger defaults to a mode in which you have to use a keyword to get it to evaluate a statement. Lost? Here’s what I mean:

Say you start the debugger here:

1
2
result = resource[xml_obj.api_call_string].get
(rdb:1)

Then you want to take a look at the “xml_obj” variable. If this were (for instance) Python’s pdb, we’d just type “xml_obj” and hit return and be done with it. Not so in ruby-debug:

1
2
(rdb:1) xml_obj.api_call_string
*** Unknown command: "xml_obj.api_call_string".  Try "help".

This is because with default settings, the debugger needs a keyword (’p') to get it to actually evaluate your statement as Ruby and not a command to the debugger itself:

1
2
(rdb:1) p xml_obj.api_call_string
"documentService/documentsByCommunity"

That gets really tedious, really fast. The debugger’s help function (’help p’) will helpfully tell you that this is because the “autoeval” option is not enabled. If you’re thick like me, you won’t see this and you’ll just continue doing “p <whatever>” until you get so frustrated you drop what you’re doing one day and go hunt down a fix.

Here is that fix from inside your code:

1
2
require 'ruby-debug'
Debugger.settings[:autoeval] = true

You can also do this inside the debugger:

1
2
(rdb:1) set autoeval
autoeval is on.

Rails already does it via Rack middleware

You might be wondering why the debugging experience is different in Rails than in Ruby you’ve written elsewhere. I did too — remembering that this ‘p’ business isn’t necessary when I run the debugger as an option when I start up Mongrel in a Rails app. So I went digging for the code that Rails uses to set this stuff up. Those settings come from a piece of Rack middleware that lives in lib/rails/rack/debugger.rb. Here’s the class definition:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
module Rails
  module Rack
    class Debugger
      def initialize(app)
        @app = app

        require_library_or_gem 'ruby-debug'
        ::Debugger.start
        ::Debugger.settings[:autoeval] = true if ::Debugger.respond_to?(:settings)
        puts "=> Debugger enabled"
      rescue Exception
        puts "You need to install ruby-debug to run the server in debugging mode. With gems, use 'gem install ruby-debug'"
        exit
      end

      def call(env)
        @app.call(env)
      end
    end
  end
end

For more info on how Rails uses Rack, this is a pretty handy page from the Rails guides.

Moving to jQuery from RJS: Getting Started

Props to this guy’s post.

Some parts are kind of confusing, but it’s a testatment to how much code he posts that I didn’t even realize he was French until I sat down to write this post and read it more carefully — he communicated mostly in code.

He gives a good Rails application.js file for you to start out with — basically it provides a bunch of handles for things you want to remote w/ XHR. They use the new-ish jQuery method unbind to make sure that regular events on items designated as AJAX get overriden. Pretty slick and a good way to think of jQuery’s usage in an app context. So far, I hadn’t really used it for AJAX beyond a thing I wrote to enable cross-domain MX record validation.

Example: remote links

Rails provides the link_to_remote helper to let you create links that will trigger a GET over XHR. This application.js defines a jQuery function for that and then binds it to a certain class of links — “get”:

1
2
3
4
5
6
7
8
jQuery.fn.getWithAjax = function() {
    this.unbind('click', false);
    this.click(function() {
      $.get($(this).attr("href"), $(this).serialize(), null, "script");
      return false;
    })
    return this;
  };

Which is then set with this:

1
$('a.get').getWithAjax();

Now any anchor with class “get” on it will result in a remote call to the URL in that anchor’s href. Combined with a respond_to block in your controller to handle Javascript and a Javascript template file, you can use links like this to (for instance) load ActiveRecord objects into a page using AJAX. Instead of “show.erb.html” your controller’s show method is handled by “show.js.erb”. This block in the show method of the controller ensures that it is activated correctly:

1
2
3
4
respond_to do |format|
  format.html
  format.js { render :layout => false }
end

Because the call came in over XHR, the controller sees the format as being JS and responds with the instructions set in the block passed to format.js. Rendering without layout ensures that nothing but the rendered data plus the template is returned.

Notice that the AJAX call in the above snippet from application.js uses the “script” datatype. This specifies that the returned data should be evaluated as Javascript, which is what we want, because the returned data includes the jQuery-based instructions we have inside show.js.erb, and those need to get evaluated (not just displayed) in order for the page to look right.

An aside: One thing that this makes me think about a lot is how important visual design is when you’re developing an application. Your design has to correspond concretely to a DOM with all sorts of manipulative handles (ids and classes) and all sorts of custom functions built to do various things to/with them. You’d damn well better draw a decent picture of this and give the elements of it some good names that make sense. In fact, I think a lot of the true work in programming involves drawing pictures (I still model some embarrassingly simple relationships with pencil and paper), but that might just be the way that my brain works.

Anywho, I took the above application.js and used it as the basis for a conversion from RJS to jQuery in a Rails app I’m working on. I’ll probably end up adding quite a bit to his stuff as I go, but having this file around made starting the transition process a lot easier.

I expect to do some more posts on the conversion as I go, since I haven’t found a whole lot of stuff yet that’s oriented toward “strategies for using jQuery with Rails” and wasn’t written in 2007. RJS kept me from dealing w/ JS directly as a major component of my app, but those days are over now that I’m committed to unobtrusive JS via jQuery, and a more thought-out approach will be necessary.

Profile your Rails RSpec and find your slow tests fast

Long-as-hell Ruby on Rails RSpec test running times are making you ask “what the deuce?” Specs are taking way too long to run, but the prospect of looking through them all one at a time to find offending external dependencies, net calls that should be mocked, etc is driving you to drink. You just want a read-out of the tests that are taking the longest so you can refactor ASAP.

Sound familiar?

I was in this boat until I found out about the profiling command:

1
$>spec spec -f profile

The double “spec” here can be a bit confusing. The first is the command, and the second is the directory (RAILS_ROOT/spec) that you’re running it on. The -f is the format flag. You can see a list of all formats with:

1
$>spec --help

Basically you’re just passing the “profile” argument to the formatting command. It gives you a readout of the 10 most time-intensive specs at the top and then a nicely verbose list of all pending and failed tests. Using this list, I was able to go straight to the most obnoxious offenders and eliminate the external dependencies (these specs happened to be fetching feeds) that were slowing my test suite down. In less than 15 minutes, I had chopped my execution time down to 10% of what it was before I started.

Huzzah!

Autotester and GrowlGlue – an adventurer is me!

Setting up autotest earlier today was kind of an annoying, semi-humbling experience. A few things that people should know to save themselves some trouble:

  • Everyone calls it autotest, but it’s actually ZenTest that you need to install. ZenTest is a larger testing package, of which autotest is merely one part.
  • Autotest runs as a separate process (which you should background — the ‘&’ is your friend!) and watches your Rails dir after you have it turned on. This last bit took me some time to figure out, as the otherwise excellent RSpec Peepcode screencast completely glosses over this point. I kept waiting for the magic to happen when I hit “save” in TextMate, but I didn’t have the process running from the command line. Magic doesn’t work. I should stop expecting it to.
  • Do yourself a favor and vastly simplify your autotest–>Growl connection by using Collin VanDyck’s GrowlGlue gem as the basis for your .autotest config file.

As of right now, I’m sitting here with just the basic GG config. I’m sure I’ll expand/customize tomorrow, but I’m just happy for now that I was able to get a working setup with just one line of code, as the normal way to get the connection going involves a decent amount of crap. After you get that going, GrowlGlue lets you set up all sorts of customization of the notifications — including custom messages, custom notification icons, and even speaking your test results through OS X’s built-in text-to-speech support — in nice, neat Ruby statements.

It’s nice to have something get in my face about my tests, and it’s also nice to have something that automatically makes you want to get your tests passing and running faster. Autotest provides you with the nagging voice that says “get your tests running right, holmes!” It’s good to strike this longstanding to-do off my list.

Late update: Turns out that running autotest in the background isn’t really ideal since you might sometimes want to cancel a running suite or check out the time elapsed since you started a given test set. What I’m looking for now is a way to see how long it takes any individual test to run so that I can find the offenders that are kicking up the aggregate time.

Tags: , ,