Archive for the UI Category

On an early Rails project I elected to use instantiated fixtures. My rationale was that it would make my test code cleaner and easier to understand. Sure, test_helper.rb warned me that they would be slow, but how bad could it be?

Well, pretty bad as it turns out. The average execution time of my test suite (with 1052 tests) using instantiated fixtures was around 590 seconds. That’s almost 10 minutes.

Suspecting that it might be the instantiated fixtures that were slowing things down, I modified a couple of tests to see if they could be sped up by switching to standard fixtures. The results were promising, so I switched everything.

The average execution time fell to 123 seconds. That’s a factor of 4.77 difference. In other words, my test time dropped from almost 10 minutes to just over two minutes.

The funny part is that instantiated fixtures didn’t make the code that much cleaner anyway, the reason being that model names would often end up embedded in fixture names. For example, if I had a User model, I might end up referencing a fixture as follows:

@user_in_more_than_one_group

The fixture was named this way because it wouldn’t make much sense if the name wasn’t prefixed with ‘user’. But when you think about it, there’s not much difference between this and the following:

users(:in_more_than_one_group)

So when I shifted away from instantiated fixtures, my code got only slightly more verbose, but the test execution time dropped by almost 80%.

Now it could be argued that these aren’t particular good fixture names, and that if they are for testing specific scenarios, I’d be better off using something like Factory Girl or Machinist. That’s a good point, but unfortunately I’m not in a position to make that change at the moment.

The bottom line is that I got caught out by just how slow instantiated fixtures are. Your results may differ, but it’s definitely worth investigating if your tests are slow and you’re using instantiated fixtures.

This is a short one, but we’ve had to do it a couple of times so I thought I’d put it up.

As you may be aware, Rails 2.2 introduced a new format for test names. Where you once might have had:

def test_should_do_stuff
  ...
end

You can now have:

test 'should do stuff' do
  ...
end

We’ve found this much easier to read and type - especially when your test names start to get big, or would be more readable if they contained characters that aren’t valid in Ruby method names.

However, if you’ve got lots of existing tests and want to shift them across to this format, it can be a pain to do it manually. Unless you’ve got a Ruby script, of course:

directory = 'unit'
Dir.mkdir("#{directory}.new")
Dir.new(directory).entries.each do |entry|
  original_filename = "#{directory}/#{entry}"
  File.open("#{directory}.new/#{entry}", 'w+') do |new_file|
    File.open(original_filename).readlines.each do |line|
      new_file.puts(line.gsub(/def test_*(.*)/) do |match|
          "test '#{$1.gsub('_', ' ')}' do"
        end)
    end
  end unless File.directory?(original_filename)
end

..which you’ll also find in this gist.

If you go into your ‘test’ folder and run this script, it’ll create a new directory called ‘unit.new’, that contains copies of all of your original unit tests, converted to the new format. Change ‘unit’ to ‘functional’, and it’ll do the same for your functional tests. Note that this will not do tests in subdirectories. YMMV. Feel free to steal and modify as you see fit.

The Problem

A while back we had a Flex client that needed to be able to display search results received from a server. The server was designed RESTfully, returning XML results to the client. The Flex client would display these results nicely to the user, and when the user clicked on a result, their browser would be directed to a HTML page for editing the actual item.

The problem was that, when a client clicked on a result, we were manually constructing the resource URLs in the Flex client from the IDs buried in the search results. The Flex code looked a bit like this:

navigateToURL(new URLRequest(’/item/’ + result.id +”/edit”),”_self”)

Furthermore, we had an impending need to support lots of different types of resources, so our logic for assembling URLs was about to become rather convoluted.

A Solution

Put the URLs into the search results. It’s blindingly simple (when you think about it, we do it all the time with pure HTML sites), but requires a subtle shift in mindset when you’re writing a fat client.

The solution was prompted by an article on REST Anti-Patterns I had read on InfoQ. - in particular, an anti-pattern called ‘Forgetting hypermedia’:

The first indicator of the “Forgetting hypermedia” anti-pattern is the absence of links in representations. There is often a recipe for constructing URIs on the client side, but the client never follows links because the server simply doesn’t send any.

It goes on to suggest that:

a client should have to know a single URI only; everything else…should be communicated via hypermedia, as links within resource representations.

You wouldn’t want to take this to an extreme, but it’s worth aiming for.

This approach helped simplify our code. We tweaked our server to write the resource URL into our XML, then had the Flex client simply navigate to the URL.

navigateToURL(new URLRequest(result.edit_path),”_self”)

Furthermore, this solution was somewhat polymorphic - a link to any sort of resource could be passed back and the client would always be able to navigate to it.

Caveats

The only catch was that we had to tweak the server to manually write the paths into the XML. As our server was a Rails app, we found it easiest to just add a ‘.xml.erb’ file to our views directory:

xml.results do
  @results.each do |result|
    xml.result do
      xml.tag! :name, result.name
      xml.tag! :description, result.description
      xml.tag! :edit_path, edit_polymorphic_path(result)
    end
  end
end

Note the use of edit_polymorphic_path to ensure that the path to any sort of resource can be written out.

My name is Mark. And I like rich clients.

There, I said it. I don’t like web applications. I never got Gmail as an interface. It never quite worked the way I wanted it to. I like eBay as a service, but not as an experience.

Over the last year I have found myself using NetNewsWire, not Google Reader.  I use OmniFocus, not RememberTheMilk.  I like having my data available everywhere, I just don’t want to use a browser to see or manipulate it.

I get that the interweb has allowed us to explore, connect and transact. Awesome. But now that we have the data and services the focus must shift to how we use it. The usability of most web applications is still well behind that of rich clients.  We need to get better.

So, we are faced with two alternatives. Try to make web applications better, or move to web enabled rich applications.

I favour the latter. Here’s why:

Rich clients work faster. Rich clients have tighter integration with the keyboard. You don’t need to be connected to the Internet all the time. Enough?

No! They also have tighter integration with the device they are running on. An iPhone application knows it has GPS and an accelerometer. It can do things you can’t do through a browser.

So let’s use the device well. Let’s optimise the experience for the device we are on. If we are on a mac I want Growl support. If we are on Windows then save data frequently.

But that is expensive to develop I hear you say. Yes. I didn’t say this would be cheap. However, in recent years we have gotten much better at building services faster (Spring: thank you.  Rails: thank you. SOAP: are you still here?).  So now that we have saved all that time on the back end, let’s spend a little more time on the front end.  

Please?!?

We have a new release of the GWT/Spring Shine Reference project out here (ver 0.3), which is an important improvement on the previous releases.

  • Now includes proper Data Layer : using Spring 2.5 annotations, Hibernate 3.2 and integrated HSQLDB runtime memory database.
  • Upgraded GWT gui to include save/delete/select functionality linking into the exposed Spring services
  • Maven now builds deployable war files for both the presentation (gwt) and service (spring) layers that can be dropped into a standard Tomcat install.

All of this should “just work” straight out of the box - tested on linux (fedora), mac and windows systems. Follow the “Getting Started” instructions on the project page.

Ruby on Rails comes with a lot of nice helper methods for generating the JavaScript driving the AJAX calls to your controllers. Handling the responses from the HTTP server becomes a snap too, with Rails providing a few simple callbacks to handle the response from the server:

But what if the server doesn’t get a chance to respond at all? What if the user’s browser has been unexpectedly disconnected from the Internet? What if your server - god forbid - has crashed?

Most AJAX applications in the wild will simply sit there forever waiting for a response. Certainly, that’s what happened to us when we first tested such a scenario. This is unacceptable: if the browser is unable to communicate with the server, we need to let the user know somehow.

Internally, Rails uses a cross-platform Javascript library called Prototype to do the heavy lifting when making AJAX calls. When you call a helper method like link_to_remote, Rails generates code to instantiate a Prototype Ajax.Request object (or a Ajax.Updater object in some cases) to make the remote call when a certain event occurs. In the case of link_to_remote, this will be when a user clicks on the generated link.

Many of the helper methods accept a common set of options which provide callbacks for handling success or failure using the following callbacks:

  • :success will be executed if the server responds to the AJAX request with any sort of 200 HTTP OK code.
  • :failure will be executed if the server responds to the AJAX request with anything *but* a 200 code.
  • :complete will be executed after the AJAX request has finished, irrespective of the result.

These callbacks can be mapped to corresponding callbacks in Prototype on a one-to-one basis. For the above callbacks, the corresponding Prototype callbacks are called onSuccess, onFailure and onComplete, respectively. Unfortunately, only the “complete” callback will be triggered if some fatal error occurs when communicating the server - “failure” will only be triggered if we get a response back from the remote host indicating a server-side. We have no way of determining what will happen if the browser is unable to communicate with the server at all.

So how do we detect server outage? Well it just turns out that if your browser is unable to communicate with the server, an exception will be thrown. We can actually use this as a basis for detecting server outages and other classes of errors that might occur browser-side. For this purpose, Prototype provides onException which is triggered by your browser if any sort of exception is thrown while the AJAX call is in progress. If we can tap into this callback, we can ensure our AJAX methods will dutifully report any problems that might occur.

Unfortunately Rails doesn’t yet provide access to this callback out-of-the-box, so there is no “:exception” callback available to the Rails helpers. We don’t want to clutter our templates with ugly JavaScript: we’d prefer to keep with the existing Rails conventions if we can. So what can we do?

PrototypeHelper#build_callbacks is used by remote_function to generate the Javascript responsible for making an AJAX call in helper methods like link_to_remote, form_remote_tag and others. It turns out that this little method exposes virtually all the callbacks available to Prototype *but* onException.

This is the hook we’re looking for: here we override and adapt the original code in PrototypeHelper#build_callbacks to add the following method to our ApplicationHelper:

include ActionView::Helpers::PrototypeHelper # ... def build_callbacks(options) callbacks = {} options.each do |callback, code| name = 'on' + callback.to_s.capitalize if CALLBACKS.include?(callback) callbacks[name] = "function(request){#{code}}" elsif callback == :exception callbacks[name] = "function(request,exception){#{code}}" end end callbacks end

This makes the :exception callback available to Rails using the familiar notation seen for the other types of callback. :exception is somewhat different in that it provides the exception object thrown internally available to your callbacks as the “exception” variable. Outside of that, it’s just like any other callback.

With this new callback available to us, we can then override the AJAX helper methods to include our error handling code in ApplicationHelper. As an example, here’s how we’d do it for form_remote_tag:

alias old_form_remote_tag form_remote_tag def form_remote_tag(options={}, &block) # In the event of a network failure (or some other error), we want to display an error message options[:exception] = (options[:exception] || '') + 'alert("Anerror occured while communicating with the server. Please try again later.");' + # Bubble the javascript exception up to prevent the caller from continuing execution (failure # to do this may result in multiple error messages being displayed!). 'throw exception;' old_form_remote_tag(options, &block) end end

With this code in place, any attempts to submit a form via AJAX will include our special error detection code, so we can rest at ease knowing our users will be notified if something goes horribly wrong at the network or language leve.

When using this technique to check, you have to be quite careful in your JavaScript code. Where any language- or browser-level exception that was thrown during the AJAX request was once ignored, it will be caught by the :exception callback. This means syntax errors in the response Javascript, bad content types (e.g. a content type of “text/javascript” with a body of HTML) or other errors will trigger the :exception callback. Unfortunately there doesn’t seem to be an obvious way to get more information about the nature of the error. For our purposes, however, this seemed to be enough if we were careful with the AJAX responses.

A further improvement to this approach might use a timeout mechanism to provide a hard limit for AJAX requests: if the server doesn’t respond with data within X seconds, abort the request and display an error. This would remove the reliance on the browser reporting errors via an exception, resulting in somewhat more robust code - the feedback may not be as immediate as if one were using exceptions, however.

Don’t leave your users out in the dark: keep them informed if things go wrong with an AJAX request.

Once in a while new technologies mature and coalesce together to provide a new and viable platform that radically change the traditional development landscape. In recent years Ruby on Rails has been the poster child of all that is new and groovy; the “must learn” skill for developers, leaving behind those “legacy” Java systems built over the last ten years.

It looks like GWT (Google Web Toolkit) is challenging those ideas. We’ve written an article explaining the steps involved putting together a multi-tiered system using GWT and Spring together (with both layers built by Maven). This also comes with an Open Source reference project showing in detail how to get up and running very quickly. Full details here.

What makes me particularly happy about all this is , is that it looks like there is still life in the old Java dog yet :)

Leopard and Rails


After having gone through the pain of installing Ruby on Rails on my MacBook Pro running Tiger (OS X 10.4) I was pleased to see that Leopard (OS X 10.5) ships with Rails ‘pre-installed’ and ready to go.

So, after I upgraded my installation on Friday night I was perplexed when trying to run my Rails apps. Why was it broken?

In the end, it turns out there were several problems.
(more…)

It takes almost ten seconds to start a Rails test on my Windows XP box. The test may report that it took it a fraction of a second to run, but it actually takes about ten seconds for it to start. The Rails Console and Mongrel have the same problem, but I can deal with that. However, with unit tests, it’s not acceptable because rapid feedback from tests is the key to rapid development.

I’ve had JUnit tests using Spring and Hibernate that start faster than this. And in Java, incremental compilers (for example, the one that comes with Eclipse) tell me immediately when I’ve stuffed up syntax. With interpreted Ruby on Rails, I have to wait ten seconds just to be told that I’ve made a typo.

To experience the problem, all I have to do is create a new Rails project, create a single model, and then run the test for that model. It takes ten seconds to start the test, give or take a second or so. Trying JRuby is not an option at this stage because at the end of the day I need to use ferret on my project, which requires native C extensions.
(more…)

Last month I attended a seminar about Virtual Worlds and in particular Second Life, during which it was suggested that Second Life had been through the hype stage, passed over the bell curve of growth and the “cool” factor, and was now on the other side of the curve with as many articles in the press concerning problems and issues than there were previously praising it.

Is the same happening with Rails?

For the last couple of years there has been a great deal written and tried with Rails which has been overwhelmingly positive (and in the main rightly so). However, I am detecting a swing in the coverage, and in particular the recent blog from cdbaby.com describing why a Rails re-write of a PHP system was completely abandoned, details here.

There have been a number of successes at Shine using Rails, and it is a great technology, but is it really that good a fit in the enterprise beyond new greenfield systems? Is there compelling reasons to replace the (in the main) Java systems we have built and maintained over the last 10 years? Is GWT a better solution for existing corporate systems - even just from the point of view that the retraining involved in GWT is trivial for a Java developer as GWT development is all written in Java? Or will improvements in Rails, for instance JRuby, allow greater integration into existing systems and hence speed its adoption?

So back to the original point, where on the bell curve is Rails….