Skip to main content

Progressive enhancement in Rails with REST

This article has been migrated from f3 Internet, with permission.

This article presents a method for enhancing a user interface built with Ruby on Rails to show a link to a RESTful operation if Javascript is available or a form button if not.

Chances are you’re already familiar with the term “progressive enhancement” (AKA “graceful degradation”). If not, see the section called what is progressive enhancement at the end of this article.

The problem

REST requires that different operations use different HTTP request methods, depending on the nature of the operation. If you’re getting information it’d be a GET request, if you’re creating something it’d be POST, then PUT for updating and DELETE for removing.

The problem is that web browsers don’t currently support all of these methods. A normal link on a web page does a GET request, a form can do a GET or a POST. That’s it.

Rails deals with this limitation in one of two ways. The simplest uses a form to send the request, with a hidden field that states what method should be used. This is fine if you’re gathering data from the user, but if you only want a simple link you have to use the second method, which uses Javascript to augment the link and submit an invisible form when clicked.

The use of Javascript presents a problem – it is not at all accessible because it assumes that Javascript is supported and the link won’t work otherwise.

The solution

In a nutshell, you assume that there’s no Javascript and present a form button, but then use Javascript to replace the form with Rails’ magic link.

Imagine we have written a basic search engine. Each search result has a ‘bookmark’ link next to it that allows us to store the result for later perusal. So, we need a link that adds a result to the database – with REST this could be a POST request that adds a record to the database, or it could be a PUT request that alters an existing record. Either way, we output a form button in our view because it doesn’t require Javascript:

Next, we progressively enhance the view and use Javascript to replace the button with a link (remove the space from < % or < %= wherever they occur):

< % form_tag add_bookmark_path(id), :method => :post, :id => "bookmark_#{id}" do %>
  < %= submit_tag t(:bookmark) %>
< % end -%>
<script type='text/javascript'>
  //<![CDATA[
  $('bookmark_< %= id -%>').replace('< %= escape_javascript(link_to(t(:bookmark), add_bookmark_path(id), :method => :post, :title => t(:bookmark))) -%>');
  //]]>
</script>

If the user doesn’t have Javascript they’ll see the button. If they do they’ll see the link. Everything is still RESTful. Everyone’s happy.

Note that the Javascript requires the form to be given a unique id so that it knows what element to replace. I’ve also used the I18n t method to ensure ‘bookmark’ is output in the appropriate language (just replace with a string if you’re not using I18n).

An alternative

One alternative would be to style the form button to look like a link, using something like XDressed Clickables. I chose not to do this for two reasons:

  1. It relies on CSS, which may not be supported.
  2. Styling forms is notoriously difficult and likely to be hard to maintain for multiple browsers that change over time.

What is progressive enhancement?

In terms of UI design, progressive enhancement is the act of improving the interface as technologies become available. The base level for web pages is HTML, with all its glorious capabilities. That alone should be enough to present someone with the most relevant content. The next level up could be considered CSS, whereby the content is enhanced with visual design. Next comes Javascript to provide a (far) greater level of interactivity. Next comes a myriad of different technologies.

The point is that with all the wonderful tools at our disposal, there is no reason not to start from scratch and build up an interface that is usable and accessible – the cost being negligible next to the benefit. Don’t take my word for it, just search for it.

By the way, “graceful degradation” is a term synonymous with “progressive enhancement” – they’re both sides of the same shiny coin.

Posted by Stephan on 11/09/2009.


Comments

Comments closed.