Crossing borders: Ajax on RailsWhy Ajax works so well with Ruby |
Level: Intermediate Bruce Tate ([email protected]), President, RapidRed 05 Dec 2006 The hype for Ajax, a technique for making Web pages more interactive, is in overdrive. The Ruby on Rails framework is also flourishing, partly on the strength of its excellent Ajax integration. Find out what makes Ajax on Rails such a powerful combination. The previous two Crossing borders articles (see Resources) walked you through Streamlined, a Rails add-on that makes effective use of scaffolding to generate simple, Ajax-enabled user interfaces quickly. Unless you've been hiding under a rock, you recognize Ajax as a programming technique that uses XML, JavaScript, and Web standards to create highly interactive Web pages, such as those you'll find at Google Maps and hundreds of other sites. Several readers of the Streamlined articles asked me to describe the way Ajax works on Ruby on Rails. This article walks through a couple of simple Ajax examples and, along the way, shows you what makes the Ruby/Ajax combination so successful. In the next article in this series, I'll dig into JavaScript as a programming language. Ajax defined Ajax stands for Asynchronous JavaScript + XML. Jesse James Garrett, an information architect, came up with the term in 2005 to describe a technique that had seen niche use for nearly a decade (see Resources). Ajax use then exploded, with a simultaneous growth in libraries, popular Web sites, and literature. Ajax redefines the basic browser's usage model, which was to render a page at a time. Ajax lets the browser communicate with the server between page updates. The upside is a richer user experience, at the cost of complexity. Ajax works by sending XML between the client and server using JavaScript client-side libraries. Ajax developers can send asynchronous requests from the client at any time, so user interactions can continue while the server processes the requests. This is the flow of an Ajax request:
All Ajax applications use an approach that looks something like this sequence. For example, consider an application that lets you maintain dictionary words with their definitions. Old-style applications would force a new page view for you to edit a definition. Ajax would allow in-place editing, by replacing definition text with an entry field, and then replacing that form with the updated definition. The components of an Ajax solution are:
This event/request/response/replace model is the core model for most Ajax applications, but if you're new to Ajax, you'd be surprised at the number of available libraries and the broad differences among them. Many Ajax frameworks dot the industry landscape, with frequent overlap and no sure winners. In the Java marketplace alone, dozens of libraries are in use, including Echo, Dojo, DWR, the Google Web Toolkit (GWT), Java Web Parts, AjaxAnywhere, AjaxTags, Scriptaculous, and Prototype. These frameworks use dramatically different approaches. Some, such as GWT, seek to hide any JavaScript by providing Java libraries that generate JavaScript code. Others aim to make JavaScript easier to use. Some are wildly comprehensive, such as Dom4J, and others simply strive to solve one small problem well. As with many popular new technologies, this checkerboard landscape of solutions will be difficult to navigate for quite some time, and the debugging tools, UI practices (such as the Back button), and wise development practices will materialize slowly. The strength of Ajax libraries on the Java platform is their diversity. That's also the weakness, because that diversity breeds indecision, integration concerns, and complexity. With Ruby on Rails, the experience is dramatically different for two reasons. First, Ruby on Rails has one core Web development platform: Ruby on Rails. Second, most of the Ajax development experience on Rails so far has centered around two core frameworks: Scriptaculous and Prototype (see Resources). The Rails approach, using run-time code generation and custom tags, insulates you from the complexities of JavaScript. It's time to see for yourself. As always, if you want to code along, you need to download Rails, which comes with the necessary Ajax frameworks (see Resources). Crack open your Rails environment, and take a look with me.
A simple Rails application without Ajax To use Rails and Ajax, you'll create an empty project and generate a controller with two methods. One controls a simple page, and another sets up an Ajax response. Type the following commands:
The first and second lines generate a Rails project and switch to the new directory. The third generates a controller called Listing 1. A controller with two empty methods
You'll first build two simple views without Ajax and then tie them together with Ajax. Edit the show.rhtml view in app/views/ajax and make it look like Listing 2: Listing 2. A simple view
The code in Listings 1 and 2 includes no Ajax support, but I'll dissect it anyway. First, look at the controller in Listing 1. Two empty controller methods process incoming HTTP requests. If you don't explicitly render a view (using a Now turn your attention to the view in Listing 2. Most of the code is simple HTML, with the exception of the As you've seen in previous Crossing borders articles, Ruby replaces the code between Figure 1. A simple user interface without Ajax In your browser, click the menu options to view the page source (View > Source in Internet Explorer and View > Page Source in Firefox). You'll see the code in Listing 3: Listing 3. The view generated by show.rhtml
Notice the link code in Listing 3. The template shields the Rails user from the tedious and error-prone HTML syntax. (The Ajax code works in the same way: you use helper methods to drop in JavaScript code that manages the remote requests and HTML replacement for you.) If you click the link, you'll see the default view for the Listing 4. Rendering the time
Now, when you click the link, you get the view in Figure 2: Figure 2. A view with no Ajax You can immediately see a problem with this UI. The two views don't belong on separate pages. The application represents a single concept: click a link to show the time. To update the time repeatedly, you need to click the link and then the Back button each time. You might solve this problem by placing the link and the time on the same page. But if the show page becomes very large or complex, redisplaying the whole page is wasteful and can lead to too much complexity.
Adding Ajax Ajax lets you update just a fragment of your Web page. The Rails libraries do most of the work for you. To add Ajax to this application, you need to do four things:
To get started, change the code in app/views/ajax/show.rhtml to look like Listing 5: Listing 5. Changing the show view to use Ajax
I've made a few changes. First, to handle the configuration, I simply included the requisite JavaScript libraries directly in the view. Usually, I'd have more views, and to avoid repetition I'd include the JavaScript files in a common Rails component, such as a Rails layout. This example has only one view, so I'll keep things simple instead. Second, I changed the link tag to use
In Listing 5, you can also see the empty In your browser, load the page http://localhost:3000/ajax/show. Click the link, and you'll see the result in Figure 3: Figure 3. A view with Ajax To get a good feel for what's happening here, view the source for the Web page. Listing 6 shows the code: Listing 6. The results of the show template, enabled for Ajax
Notice the list of JavaScript includes. The Rails helper --
Using other Ajax options Ajax can generate powerful behaviors, even some unexpected ones. For example, my users might not notice the updated time link. The Listing 7. Adding effects
The best Ajax effects draw temporary attention to your change but don't last forever. Your goal should be to alert users to the change without disrupting their workflow. Techniques like this yellow fading highlight, or content that slides in or fades out, won't be permanently distracting. So far, the link is the only trigger you've seen. Ajax has several others you can use, with some driven by users and others driven by programmatic events, such as a timer. Something like a clock should not necessarily require user intervention. You can update a timer periodically with Ajax with the Listing 8. Periodically call the remote method
Figure 4 shows the result: a clock that updates at one-second intervals without requiring user interaction: Figure 4. A clock periodically updated with Ajax Though the code in the Rails view is similar to the version without Ajax, the underlying code is much different: this version uses JavaScript instead of HTML. You can see the code in Listing 9 by viewing the source in your browser: Listing 9. The source for periodically_call_remote
Pay close attention to what's happening here. Instead of working with tiny fragments of custom JavaScript, you are effectively working at a higher level of abstraction, and the Ruby on Rails templating system makes the usage model feel quite natural. As I pointed out earlier, I'm rendering text directly from a controller. That simplification makes it easy to get started but won't hold up over time. My views should handle presentation, and my controllers should marshal data between the view and model. This design technique, called model-view-controller (MVC), makes it easier to isolate changes to a view or model. To enable this application for MVC, I can simply let Rails render the default view, and the contents will replace the previous contents of Listing 10. Refactoring
Change the view in app/views/ajax/time.rhtml to resemble Listing 11: Listing 11. Using a view to render Ajax content
The controller method sets an instance variable called
Other uses for Ajax in Rails The Rails Ajax experience is broad and deep -- much deeper than I can cover in a single article or even a series. Rest assured that Rails Ajax support solves some other problems as well. These are some common uses of Ajax in Rails:
Conclusion Ajax is not without its problems. When things go well, the whole experience can be breathtaking. When things break, you may find that debugging takes on a whole new dimension, and debugging techniques and tools still don't match those you'll find in other languages. Ruby on Rails does have one core advantage: simplicity. The Rails wrappers, combined with fantastic community support, make it easy to break into this new world with a very low initial investment. But the Rails support can take you only so far. Two frameworks that do not span the whole Ajax continuum will not satisfy every user. The Java language has many more Ajax frameworks and approaches to choose from. You can find much greater flexibility, and you'll also find a fantastic support base. But flexibility comes at a price. You'll need to pick not only a strong Ajax framework, but also a Web development framework. For example, integrating the JSF framework is a dramatically different experience from integrating Struts. New technologies often call for simplification. Ajax on Rails may be just the ticket for problems that require the sophistication of Ajax in the UI but none of the advanced enterprise-integration features the Java language provides. Next time, I'll take a deeper look into JavaScript. Until then, keep crossing borders. Resources Learn
Get products and technologies
Discuss
About the author
|