BUY THIS BOOK
Add to Cart

Print Book $39.99


Add to Cart

Print+PDF $51.99

Add to Cart

PDF $31.99

Safari Books Online

What is this?

Add to UK Cart

Print Book £28.50

What is this?

Looking to Reprint or License this content?


Ajax on Rails
Ajax on Rails By Scott Raymond
January 2007
Pages: 350

Cover | Table of Contents | Colophon


Table of Contents

Chapter 1: Introduction
Where, where lieth the fatally named, intractable Ajax?
Sophocles
Purely in terms of buzz, two of the hottest web-development terms in recent memory are Ajax and Rails. Ajax was just coined in February 2005, and seemingly overnight it sparked summits, workshops, books, and articles aplenty. At the beginning of that year, Rails was still a newborn getting scattered discussion in developers’ weblogs. Almost two years later, it claims hundreds of thousands of downloads, nine slashdottings, two conferences, and tens of thousands of books sold.
Why all the noise? Are these technologies fads or worthy of lasting attention?
There are solid reasons to believe that both Ajax and Rails will be significant features of the web development landscape for some time. Big players are leading by example: Yahoo, Google, Apple, Microsoft, and IBM have all started using and touting Ajax techniques, and Rails has become so associated with web startups that it’s almost cliché. And for each high-profile implementation, there are dozens created for smaller audiences or for internal use. As awareness of both technologies grows and they prove their value, the snowball will only roll faster.
Ajax on Rails is the definitive guide to where these two technologies converge.
This book will help you use Rails for building richly interactive web applications with Ajax. It provides comprehensive reference and detailed examples for every JavaScript method that Rails offers, as well as its JavaScript-generating methods. More than just recipes, you’ll also get a thorough, low-level understanding of what’s happening under the hood. And beyond the how-to, we’ll spend time considering when Ajax is (and isn’t) appropriate and the trade-offs associated with it.
This book is written for developers who have experience building for the Web—working knowledge of HTML, CSS, and JavaScript is assumed. Using Rails will require some use of the command line, so you should be familiar with those facilities of your operating system. If you are new to Rails, this book provides a quick introduction, the big picture, a walk through the installation process, and some tips on getting started. But to develop full applications, you’ll benefit from a good guide to Ruby itself, as well as the other Rails components. Fortunately, there are many great tutorials and references available online and in print to fill those needs, and we’ll point you to the best.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Who This Book Is For
This book will help you use Rails for building richly interactive web applications with Ajax. It provides comprehensive reference and detailed examples for every JavaScript method that Rails offers, as well as its JavaScript-generating methods. More than just recipes, you’ll also get a thorough, low-level understanding of what’s happening under the hood. And beyond the how-to, we’ll spend time considering when Ajax is (and isn’t) appropriate and the trade-offs associated with it.
This book is written for developers who have experience building for the Web—working knowledge of HTML, CSS, and JavaScript is assumed. Using Rails will require some use of the command line, so you should be familiar with those facilities of your operating system. If you are new to Rails, this book provides a quick introduction, the big picture, a walk through the installation process, and some tips on getting started. But to develop full applications, you’ll benefit from a good guide to Ruby itself, as well as the other Rails components. Fortunately, there are many great tutorials and references available online and in print to fill those needs, and we’ll point you to the best.
If you have started working with Rails and seek to deepen your skill set, this book will do just that. You’ll find dozens of examples drawn from real-world projects, exhaustive reference for every relevant feature, and expert advice on how to “Ajaxify” your applications.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
What Ajax Is
Ajax represents a significant shift in how the Web is built—and even in how it’s conceived. But it’s a really simple idea: web pages, already loaded in a browser, can talk with the server and potentially change themselves as a result. So instead of a form submission causing a whole new page to load, an Ajax form submission happens in the background and just updates the current page in place—no refresh, no flash of white as the page changes, no change in the address bar. That’s the essence of Ajax, in the concrete. It’s really that simple! While keeping in mind that simple, concrete definition of Ajax, let’s take a minute to look at Ajax in a more abstract way. First, consider how the Web traditionally works.
Think about the way the Web usually works, without Ajax. First, the browser creates an HTTP request for something on the server, say /page1.html. Figure 1-1 shows the life cycle of the request.
Figure 1-1: The traditional (non-Ajax) request model
In this model, the server sends back a response containing a page—perhaps including a header area with a logo, a sidebar containing navigation, and a footer. With the next click on a link or button, the whole cycle repeats for /page2.html: a new connection to the server, a new request, and a new page. Even the parts of the page that haven’t changed (say, the header and sidebar) are sent over the wire again. The process of sending the request, waiting for the response, and rendering a new page might take a while, and once the user has clicked, he’s effectively committed to that wait before he can proceed.
This model works fine, to a point. In fact, when the nature of your site is primarily document-centric, it’s quite desirable. But when developing web applications, it’s a bit heavy—small interactions that ought to feel responsive are sluggish instead. For example, imagine a web application for managing to-do lists. If simply checking an item off the list causes the entire page to be re-fetched and rendered, the cause and the effect are pretty disproportionate.
Remember how simple Ajax is in concrete form: it’s just pages talking with the server without a full refresh. With that in mind, contrast the traditional request model with the Ajax model, as seen in Figure 1-2.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
What Rails Is
So far, we’ve been thinking about Ajax; let’s shift now to Rails. Ruby on Rails (or more commonly, just Rails) is a full-stack MVC web development framework for the Ruby language. That’s a mouthful. Let’s break down the concepts one by one:
Full-stack means that the framework encompasses almost everything you’ll need to create a finished product. It’s perhaps a bit of a misnomer, because most applications will also require a persistence layer (a database) and a web server. But at the application level, Rails has everything needed by most projects, most of the time—there’s no need to select an additional templating system or database-mapping system.
MVC stands for Model View Controller, which is simply a way of organizing your application into chunks, according to their responsibility.
  • The model represents your domain objects (such as User, Company, Post, etc.) and interacts with the database.
  • The view deals with the user interface: generating HTML, RSS feeds, JavaScript code, etc.
  • The controller handles user input and orchestrates interaction between the model and the view.
Web applications don’t have to be organized according to MVC—many developers freely mix all three parts. But as systems get larger, the mixed-up method quickly becomes untenable and prone to error. Code can be organized lots of ways, but MVC is the Rails way and a time-tested approach to keep your application maintainable.
A framework can be seen as a set of constraints for your program. At first, that sounds like a bad thing—why constrain yourself? But it turns out that by embracing constraints for a specific purpose, you actually enable creativity, by focusing energy on the problem at hand. The Rails framework is a set of constraints that enables effective web development.
When I was in college, I studied in Paris for a while, and I often visited cyber cafés to write friends back in the U.S. The experience introduced me to non-English keyboard layouts. Usually they were French, but I also ran into German and Spanish. The layouts of all the keyboards are similar, but just different enough to be a hassle—a few letters swapped here and there, slowing down my typing tremendously. One day, while emailing a friend, I was unable to find a way to type the letter
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
‘You Got Your Ajax in My Rails!’
We’ve now looked at what Ajax is and what Rails is. But this book is about both of them together and how these two great tastes complement each other.
As discussed above, one of Rails’ mantra is frameworks are extractions. And the story of Ajax in Rails exemplifies that philosophy perfectly. During the development of another 37signals product, TaDa List (http://www.tadalist.com), the developers needed some simple Ajax functionality. Writing the necessary JavaScript for the project turned out to be painful—and pain is often the first sign that an extraction might be useful. By the time the company embarked on its next Ajax/Rails application, Backpack (http://backpackit.com), Ajax functionality had been added to the framework. The result was that Rails was one of the first web frameworks with first-class Ajax support. And because of the philosophy of extraction, it remains one of the most pragmatically useful environments to work in.
There are two sides to the Ajax/Rails coin. The first is composed of two JavaScript frameworks: Prototype and script.aculo.us. Both are bundled with and developed alongside Rails, although they can readily be used with applications in other languages, such as PHP and Java. Prototype provides convenient wrappers around XMLHttpRequest, as well as a wealth of methods for manipulating the DOM and JavaScript data structures. The script.aculo.us library builds atop Prototype and focuses on visual effects and advanced UI capabilities, such as drag and drop.
Rails helpers represent the flip side of the coin. These are Ruby methods, called from within the controller and view code that (among other things) generate bits of JavaScript that in turn invoke Prototype and script.aculo.us. The end result is that it’s possible to create very rich “Ajaxified” applications without writing any JavaScript.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Getting Up to Speed
If you haven’t yet started using Ruby or Rails, this section will point you in the right direction. If you’re comfortable with Rails basics, feel free to skip ahead to Chapter 2, where we’ll start doing Ajax. It’s outside the scope of this book to provide a comprehensive guide to Ruby, or all of Rails. Fortunately, there are dozens of excellent resources available to fill that need. In this section, we’ll point you to the best.
Getting and installing Ruby is easy on almost every platform. The official web site is http://ruby-lang.org. From there, you’ll find downloads for the latest releases. Windows users can take advantage of the One-Click Ruby Installer (http://rubyinstaller.rubyforge.org), which bundles lots of great extensions. Mac users already have Ruby installed as part of OS X—however, it’s not configured correctly for Rails use. To fix that, follow this guide: http://hivelogic.com/articles/2005/12/01/ruby_rails_lighttpd_mysql_tiger.
Ruby has a solid (and quickly growing) body of documentation, suited to all experience levels. Here are some of the best resources:
  • The Ruby web site (http://ruby-lang.org) is the home base for English-language resources on Ruby—including downloads, documentation, and news.
  • Try Ruby (http://tryruby.hobix.com) is a hands-on Ruby tutorial that runs entirely in your browser, with no need to download Ruby first. It’s a great way to familiarize yourself with Ruby’s syntax and conventions.
  • Programming Ruby by Dave Thomas, et al. (Pragmatic Bookshelf), also known as the “Pickaxe book,” is the most popular book on Ruby, for good reason—it’s full of clear explanations and vital reference. Best of all, the first edition (which doesn’t cover the latest additions to Ruby but is still immensely useful) is available free online at http://www.rubycentral.com/book.
  • Why’s (Poignant) Guide to Ruby (http://poignantguide.net/ruby) is a great, free resource for learning Ruby. Self-described as “the pirate radio of technical manuals,” it also serves as an excellent introduction to the off-the-wall sense of humor often found in the Ruby community.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Summary
In this chapter, we looked at the 30,000-foot view of Ajax and Rails. First with Ajax—its basic mechanisms, motivation, and location in the larger historical context of the Web. We deconstructed the strict acronym interpretation of Ajax and replaced it with a definition centered more on solving problems.
Then we shifted attention to Rails, Ruby, and frameworks in general. We discussed the ideals that guide the development of Rails and the history of Ajax in Rails. In the last section, we fired up the terminal and walked through installing Ruby and Rails, and making sure the whole thing works by creating an application skeleton.
In the next chapter, we’ll pick up exactly where we left off and start adding code to the skeleton application.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 2: Getting Our Feet Wet
Ho, Ajax! Once again I summon thee.
Sophocles
In this chapter, the idea is to take a walking tour, in baby steps, through some really simple Ajax examples. Rails provides a huge amount of power for doing complex Ajax interactions with very minimal code. But in order to understand what’s happening under the hood, you should be familiar with Ajax’s lowest levels (e.g., the XMLHttpRequest object). By the end, you’ll be comfortable creating XMLHttpRequest objects both by hand and by using the Prototype library. Finally, we’ll use Rails’ JavaScript helpers to create simple Ajax interactions without writing any JavaScript. With the foundation in place, you’ll have an accurate understanding of how the Rails helpers work—and also an appreciation for how much trouble they will save you.
If you’re already comfortable with Rails and basic Ajax, this chapter will be review, but you might still find it useful to at least skim the examples.
To start off, let’s do Ajax with the simplest thing that could possibly work: click a link and present a response from the server—using XMLHttpRequest directly, without Prototype or Rails’ JavaScript helpers.
Using XMLHttpRequest is often portrayed as being rocket science. But you’ll find that, with a little practice and perhaps a couple new concepts, it’s not as tricky as its reputation suggests.
If you didn’t create the example Rails skeleton in the last section, do so now, from your system’s command line:
rails ajaxonrails
cd ajaxonrails
script/server
Browse to http://localhost:3000, and you should see Rails’ welcome screen (for development purposes, script/server starts an HTTP server on port 3000). Back at the command line, let’s generate a new controller called Chapter2Controller with an action called myaction. (Since you’re already running the server in one terminal window, you’ll want to open another.)
script/generate controller chapter2 myaction
The Rails generator is used to add on to the skeleton—usually by generating new controllers and models. Of course, you could simply create a new controller file by hand, but using the generator saves typing—which prevents typos.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The Old-Fashioned Way
To start off, let’s do Ajax with the simplest thing that could possibly work: click a link and present a response from the server—using XMLHttpRequest directly, without Prototype or Rails’ JavaScript helpers.
Using XMLHttpRequest is often portrayed as being rocket science. But you’ll find that, with a little practice and perhaps a couple new concepts, it’s not as tricky as its reputation suggests.
If you didn’t create the example Rails skeleton in the last section, do so now, from your system’s command line:
rails ajaxonrails
cd ajaxonrails
script/server
Browse to http://localhost:3000, and you should see Rails’ welcome screen (for development purposes, script/server starts an HTTP server on port 3000). Back at the command line, let’s generate a new controller called Chapter2Controller with an action called myaction. (Since you’re already running the server in one terminal window, you’ll want to open another.)
script/generate controller chapter2 myaction
The Rails generator is used to add on to the skeleton—usually by generating new controllers and models. Of course, you could simply create a new controller file by hand, but using the generator saves typing—which prevents typos.
The generator has another side effect: every time you generate a controller, a corresponding functional test file is generated as well. It’s Rails’ way of reminding you that testing is an important part of application development. To learn more about the available generators and their options, run script/generate without arguments.
Go to http://localhost:3000/chapter2/myaction. You should see the newly generated view as in Figure 2-1.
Figure 2-1: Newly generated Rails controller and view
Notice that, by default, the first part of the URL determines the controller, and the second part determines the action—the method within the controller. Now edit the template for that action, which is in app/views/chapter2/myaction.rhtml. Add this bit of HTML to the bottom:
<p><a href="#" onclick="alert('Hello !');">Inline alert(  )</a></p>
As you can see, we’re creating a paragraph with a basic link—but instead of the usual
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
JavaScript Libraries and Prototype
If you’re new to Ajax, you’re hopefully starting to see that doing vanilla Ajax, without the support of any extra libraries or helpers, isn’t the trick it’s often portrayed to be. Nonetheless, the idea of writing more than a dozen lines of code to do the simplest possible task is off-putting.
Dozens of JavaScript libraries have sprung up to make Ajax easier, and one of the most popular is Prototype, which is included with Rails. We’ll cover Prototype thoroughly in Chapter 10, but for now, let’s dive in with some examples. First off, let’s redo the last example, this time using Prototype. Here is a new chunk to add:
<script src="/javascripts/prototype.js" type="text/javascript">
</script>
<p><a href="#" onclick="prototypeAlert(  );">Call with Prototype</a></p>
<script type="text/javascript">
 function prototypeAlert(  ) {
  new Ajax.Request('/chapter2/myresponse', { onSuccess: function(request) {
   alert(request.responseText);
  }})
 }
</script>
Note the first line, where we include the prototype.js source file so that it’s usable from our page. When you first generated a new Rails app skeleton, a copy of Prototype was put in the directory public/javascripts. Inside the prototypeAlert(  ) function, the first line creates a new instance of Ajax.Request, one of Prototype’s classes. The first argument takes the URL to be requested, and the second argument is a JavaScript object literal—a collection of key/value pairs, which behaves similar to a hash or associative array in other languages. In this case, the only option given is onSuccess, which is expected to be a callback function.
Note that there’s nothing in this example to handle the IE-specific versions of XMLHttpRequest and no mention of readyState codes. Prototype handles those details, leaving you with a far cleaner API.
So far, all our examples have created an alert(  ) box—which, in your real-world applications, is probably not the most common thing you’d want to do. More often, you’ll want to add or modify some content on the page. Here’s a new iteration to add:
<p><a href="#" onclick="updateElement(  )">Update element </a></p>
<p id="response"></p>
<script type="text/javascript">
  function updateElement(  ) {
    new Ajax.Request('/chapter2/myresponse', { onSuccess: function(request) {
      $('response').update(request.responseText);
    }})
  }
</script>
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Bringing Rails into the Picture
Rails provides convenient integration with Prototype, in the form of helper methods that generate Prototype calls. Next we’ll discover how to do Ajax without writing any JavaScript, using the link_to_remote(  ) helper method.
First, we need to back up a little and look at Rails’ system for handing views.
If you’ve ever used PHP, ColdFusion, ASP, JSP, or something similar, this will be a familiar concept. Embedded Ruby (ERb) lets you mix Ruby snippets into your HTML. ERb defines a set of special tags that get interpreted as Ruby; everything else is assumed to be plain HTML and is passed through untouched. Here are the special tags:
<%=  %>
The most common one, this holds a Ruby expression—which is output in place of the tag.
<%= -%>
Works just like the above but suppresses newline characters from the output after the tag, which allows for cleanly organized templates without extraneous whitespace in the HTML output.
<%   %>
This holds a piece of Ruby code but doesn’t output anything.
<%  -%>
Works just like the above but suppresses newline characters after the tag.
<%#  %>
This is a Ruby comment, which is ignored and nothing is output.
Let’s look at an example.
Remember our discussion of MVC in Chapter 1? Here is where it begins to come into play. Typically, a controller will receive a request for a page, and assemble the data needed for the view. In Rails, that data is put into instance variables (which are recognizable by the ugly @ sign that they all start with). So, imagine that we have this controller action:
def myaction
  @foo = "Hello, world!"
end
The action defines a variable called @foo, and puts the string Hello, world! into it. Our template could then contain this:
<%= @foo %>
And, when the template is accessed, <%= @foo %> would be replaced with
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Summary
We’ve covered a lot of ground in this chapter, graduallyfs building up from simple, client-side-only JavaScript, through manual Ajax calls, then adding support from the Prototype library, and finally skipping JavaScript altogether with the Rails JavaScript helpers. You should now have a very solid foundation for building Ajax with Rails, and the next few chapters will build heavily on that foundation.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 3: Introducing Prototype
The last chapter started by introducing Ajax without library support, then explored how Prototype can help, and ended with a taste of Rails’ helpers. In this chapter, along with Chapters 4 and 5, we dive deep into Prototype and its helpers—from the simplest links to full-blown interactive components with visual effects. This chapter focuses on the helpers that interact with Prototype to create Ajax-enabled links and forms. For a full reference to all of Prototype’s capabilities, see Chapter 10.
For the examples in this chapter, we’ll reuse the Rails application created in Chapter 2, but we’ll generate a new controller. So back to the command line:
script/generate controller chapter3 get_time repeat reverse
That command generates a controller chapter3 with four actions: index, get_time, repeat, and reverse. Take a look at http://localhost:3000/chapter3 and you will see a bare-bones view, as in Figure 3-1.
Figure 3-1: New controller
In the previous chapter, we kept the example views as plain as possible. This time let’s spruce it up a bit with an HTML layout and a CSS file. First create a new layout file, app/views/layouts/application.rhtml, and fill it with a basic XHTML template:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
  <head>
    <title>Ajax on Rails</title>
    <%= javascript_include_tag :defaults %>
    <%= stylesheet_link_tag "application" %>
  </head>
  <body>
    <h1>Ajax on Rails</h1>
    <%= yield %>
  </body>
</html>
For our purposes, there are two important parts. The first is javascript_include_tag :defaults, which will include Prototype and script.aculo.us (specifically prototype.js, effects.js, dragdrop.js, and controls.js), as well as application.js, if present. The second is yield—that’s where the content from your action templates will be inserted. For the sake of nice-looking templates, let’s make a simple CSS file, public/stylesheets/application.css
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Setting the Stage
For the examples in this chapter, we’ll reuse the Rails application created in Chapter 2, but we’ll generate a new controller. So back to the command line:
script/generate controller chapter3 get_time repeat reverse
That command generates a controller chapter3 with four actions: index, get_time, repeat, and reverse. Take a look at http://localhost:3000/chapter3 and you will see a bare-bones view, as in Figure 3-1.
Figure 3-1: New controller
In the previous chapter, we kept the example views as plain as possible. This time let’s spruce it up a bit with an HTML layout and a CSS file. First create a new layout file, app/views/layouts/application.rhtml, and fill it with a basic XHTML template:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
  <head>
    <title>Ajax on Rails</title>
    <%= javascript_include_tag :defaults %>
    <%= stylesheet_link_tag "application" %>
  </head>
  <body>
    <h1>Ajax on Rails</h1>
    <%= yield %>
  </body>
</html>
For our purposes, there are two important parts. The first is javascript_include_tag :defaults, which will include Prototype and script.aculo.us (specifically prototype.js, effects.js, dragdrop.js, and controls.js), as well as application.js, if present. The second is yield—that’s where the content from your action templates will be inserted. For the sake of nice-looking templates, let’s make a simple CSS file, public/stylesheets/application.css:
body {
  background-color: #eee;
  color: #222;
  font-family: trebuchet;
  padding: 0;
  margin: 25px;
}
h1 {
  margin: -25px -25px 20px -25px;
  padding: 50px 0 8px 25px;
  border-bottom: 3px solid #666;
  background-color: #777;
  color: #fff;
  font: normal 28pt georgia;
  text-shadow: black 0px 0px 5px;
}
a { color: #229; }
.box {
  border: 1px solid;
  width: 100px; height: 100px;
  padding: 5px;
  font-size: .6em;
  letter-spacing: .1em;
  text-transform: uppercase;
  margin-bottom: 20px;
}
.pink {
  border-color: #f00;
  background-color: #fcc;
}
.green {
  border-color: #090;
  background-color: #cfc;
}
.hover {
  border-width: 5px;
  padding: 1px;
}
ul {
  background-color: #ccc;
  padding: 5px 0 5px 30px;
}
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Ajax Links
Now that we’ve got a decent canvas, we can add some Ajax to the mix. Change your index.html template to look like this:
<%= link_to_remote "Check Time",
    :update => 'current_time',
    :url    => { :action => 'get_time' } %>
<div id="current_time"></div>
We’ve turned link_to to link_to_remote and added a new option, :update. The value of :update refers to the HTML element ID where the Ajax response should be inserted—in this case, a DIV. The generated HTML looks like this:
<a href="#"
   onclick="new Ajax.Updater('current_time', '/chapter3/get_time',
               {asynchronous:true, evalScripts:true});
            return false;">Check Time</a>
<div id="current_time"></div>
Take a look at the generated HTML, and you’ll see it uses Prototype’s Ajax.Updater method. All the Rails Ajax helpers work this same way: they are Ruby methods, embedded in HTML templates, generating JavaScript, calling Prototype.
You may have noticed a red flag in the generated HTML link: href="#". While technically valid HTML, this kind of “link to nowhere” is generally a bad practice. If the user has JavaScript turned off, or a search engine is indexing the page, the link will be meaningless. Whenever possible, it’s a good idea to provide a useful link, as a fallback for non-Ajax browsers. Chapter 6 covers the idea of degradability in more detail.
The essential mechanism of Ajax links is the onclick attribute, which is a way to hijack the behavior of a link. When an onclick is provided, the browser will evaluate it before following the link. The link will only be followed if the expression evaluates true (or if the user has JavaScript turned off). That’s why the link_to_remote helper puts return false at the end of the onclick attribute.
So far, this is review. Let’s dive deeper. The link_to_remote helper provides a set of callbacks so you can easily make things happen during the life cycle of an Ajax request by providing JavaScript snippets to be evaluated. For example:
<%= link_to_remote "Check Time",
    :update => 'current_time',
    :url    => { :action => 'get_time' },
    
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Forms
So far we’ve been using helpers to generate links that request information from the server, but for really interesting applications, we’ll want to send data to the server as well, and that means forms. First, we’ll create a simple, non-Ajax form. The form_tag and end_form_tag helpers create an HTML form element. For example, this:
<%= form_tag :action => 'reverse' %>
<%= end_form_tag %>
...generates this:
<form action="/chapter3/reverse" method="post">
</form>
Within a form, there are helpers to generate input fields. Here they are:
text_field_tag( name , value = nil , options = {} )
The keys in the options hash will be made into HTML attributes. For example:
<%= text_field_tag "name", "Scott",
     :size     => 5,
     :disabled => true,
     :style    => "background-color: red" %>
The helper will produce this output:
<input type="text" name="name" id="name" value="Scott" 
  size="5"
  disabled="disabled"
  style="background-color: red" />
hidden_field_tag( name , value = nil , options = {} )
Takes the same options as text_field_tag.
password_field_tag( name = "password" , value = nil , options = {} )
Takes the same options as text_field_tag.
file_field_tag( name , options = {} )
Takes the same options as text_field_tag.
check_box_tag( name , value = "1" ,
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Ajax Forms
To Ajaxify this form, all we need to do is replace the form_tag helper with its form_remote_tag alternative and add a place for the response to be inserted:
<%= form_remote_tag :update => "reversed",
                    :url    => { :action => 'reverse' } %>
  <p>Text to reverse: <%= text_field_tag 'text_to_reverse' %></p>
  <p id="reversed"></p>
  <p><%= submit_tag 'Reverse!' %></p>
<%= end_form_tag %>
The options here should look familiar, because they’re exactly the same as the options for link_to_remote. The :update option specifies which HTML element will be updated with the Ajax response, and :url provides the URL for the Ajax request. Try out the new form, and you’ll get something like Figure 3-5. As you can see, that won’t do.
Figure 3-5: Oops, that’s not right
The layout is being rendered twice, heading and all. The problem is that every action (such as our reverse) will render within layouts/application.rhtml unless told otherwise. To specify a layout (or turn them off), the action needs an explicit render statement:
def reverse
  @reversed_text = params[:text_to_reverse].reverse
  render :layout => false
end
With that line added, try the Ajax form again, and everything should work as expected, as seen in Figure 3-6.
Figure 3-6: Rendered without layout
The rendered result of the form_remote_tag uses Prototype’s Ajax.Updater, just like link_to_remote did:
<form action="/chapter3/reverse" method="post" 
   onsubmit="new Ajax.Updater('reversed','/chapter3/reverse',
     {asynchronous:true, evalScripts:true,
      parameters:Form.serialize(this)});
     return false;">
Just as the onclick attribute hijacks a link, onsubmit hijacks the behavior of forms.
The Ajax counterpart to form_for (the helper for creating forms to work with model objects) is remote_form_for. Using it works exactly like form_for, except that the options hash may also contain the usual Ajax options, such as :update and :complete.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Buttons
Notice something about the previous form_to_remote example: in the generated HTML, the only difference between a regular form and an Ajaxified form is the addition of an onsubmit attribute—the rest of the form, including the submit buttons, are vanilla HTML. Where form_to_remote creates a special, Ajaxified form with normal submit buttons, submit_to_remote does the opposite: it creates a special submit button for a plain form. For example:
<%= form_tag :action => 'reverse' %>
  <p>Text to reverse: <%= text_field_tag 'text_to_reverse' %></p>
  <p id="reversed2"></p>
  <p><%= submit_to_remote 'submit', 'Reverse!',
          :update => 'reversed2',
          :url => { :action => 'reverse' } %></p>
<%= end_form_tag %>
The first parameter to submit_to_remote determines the name attribute on the button, and the second sets the value, which appears in the button. When you click the button, the end result is exactly the same as before. However, the difference is that the form can be submitted both via Ajax or non-Ajax methods. Consider this variation with two submit buttons:
<%= form_tag :action => 'reverse' %>
  <p>Text to reverse: <%= text_field_tag 'text_to_reverse' %></p>
  <p id="reversed"></p>
  <p><%= submit_to_remote 'submit', 'Submit via Ajax',
          :update => 'reversed',
          :url => { :action => 'reverse' } %></p>
  <p><%= submit_tag "Submit non-Ajax" %></p>
<%= end_form_tag %>
In practice, a common application for submit_to_remote would be checking a form for validity before actually submitting it for creation. For example, during a sign-up process you could allow the user to check whether a chosen username is available.
The button_to_function helper creates a button that triggers a JavaScript function. Just like link_to_function, the first argument becomes the text inside the button, and the second argument is the JavaScript to be evaluated. For example:
<%= button_to_function "Greet", "alert('Hello world!')" %>
To create a button that initiates an Ajax request, you can combine button_to_function with remote_function. That helper takes the same arguments as
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Form Observers
Ajax? Why thus uncalled wouldst thou go forth?
Sophocles
The observe_field helper allows you to attach behavior to a field so that whenever it’s changed, the server is notified via Ajax. It can be used like this:
<p>Text to reverse: <%= text_field_tag 'textToReverse' %></p>
<span id="reversed"></span></p>
<%= observe_field 'text_to_reverse',
     :update => 'reversed',
     :url    => { :action => 'reverse' },
     :with   => 'text_to_reverse' %>
Notice that this works somewhat differently than the helpers we’ve seen so far. The other helpers we’ve looked at all output HTML (e.g., links, form tags). In this example, the form field is created by text_field_tag—so what does observe_field create? It creates JavaScript:
new Form.Element.EventObserver('textToReverse',
  function(element, value) {
    new Ajax.Updater('reversed', '/chapter3/reverse',
      { parameters:'text_to_reverse=' + value });
  }
)
This JavaScript creates a new instance of Prototype’s Form.Element.EventObserver class, bound to the text_to_reverse field. Whenever the field changes, the observer triggers Ajax.Updater, which we’re familiar with from Chapter 2. For a full description of Form.Element.EventObserver, see Chapter 10.
The options available for observe_field are the same as link_to_remote (:update, :url, callbacks, etc.), with a few additions. First, the :with option is a JavaScript expression that’s evaluated to determine the parameters that are passed to the server. By default it is value—which, when evaluated in the JavaScript context, represents the value of the field being observed. So if no :with option is provided, the generated JavaScript would look like this:
new Form.Element.EventObserver('textToReverse',
  function(element, value) {
    new Ajax.Updater('reversed', '/chapter3/reverse',
      {parameters:value});
  }
}
The problem here is that the parameter isn’t given a name, so won’t be available in the params object on the server side. The :with option gives the parameter a name. If :with is set to foo, the code becomes:
new Form.Element.EventObserver('textToReverse',
  function(element, value) {
    new Ajax.Updater('reversed', '/chapter3/reverse',
      {parameters:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Summary
In this chapter, we explored Rails’ Prototype helpers—starting with simple links and moving on to Ajax links and all their permutations. The discussion of link_to_remote is foundational to Ajax on Rails, because its options and callbacks are echoed through every other Ajax-related helper in the framework. After links we moved on to richer forms of interaction: buttons and forms, in their traditional and Ajaxified guises.
In the next chapter, we’ll build on this foundation and use script.aculo.us to create even richer experiences.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 4: Introducing script.aculo.us
Most of the last chapter dealt with the Rails helpers that interact with Prototype. In this chapter, we’ll shift attention to script.aculo.us, and the Rails helpers that use it. script.aculo.us provides eye-catching visual effects and transitions and powerful drag-and-drop elements.
The relationship between Prototype and script.aculo.us is close. They’re both developed in concert with Rails, and they share very similar coding styles and APIs. In fact, some of what is now script.aculo.us was originally part of Prototype. Despite the close ties, the two libraries have different goals. Prototype is designed to be an extension of JavaScript—it provides features that arguably ought to be part of the core language, such as convenient methods for data structures, DOM interaction, and easy Ajax calls. On the other hand, script.aculo.us works at a higher level, closer to the application and UI levels, by providing components built on Prototype. In some cases, those components are surprisingly complex and yet usable with just a few lines of code.
We’ll put the examples for this chapter into a new controller, so from your Rails project directory, run the generator:
script/generate controller chapter4 index
If you already created an application-wide layout (layouts/application.rhtml) and CSS file (public/stylesheets/application.css) from the beginning of Chapter 3, they will automatically be used for this controller as well.
Now let’s take a look at what script.aculo.us is most famous for: its visual effects.
The most popular component of script.aculo.us is its Effect object, which is used to attach a variety of cinematic effects to UI events. Using script.aculo.us effects, many of the slick animated transitions that people have come to associate with Flash can be accomplished without plug-ins at all, and in a way that preserves the benefits of HTML.
What about cross-platform compatibility? In general, the script.aculo.us visual effects work reliably across different browsers (Internet Explorer 6+ for Windows, Firefox, Safari, Konqeror, Camino, and, with a few exceptions, Opera). And because the animated effects are time-based (as opposed to frame-based) they work consistently on systems of different speeds. You might be wondering: just because visual effects are easy, does that mean they’re a good idea? Isn’t it just eye candy? And what does it have to do with Ajax, anyway?
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Visual Effects
The most popular component of script.aculo.us is its Effect object, which is used to attach a variety of cinematic effects to UI events. Using script.aculo.us effects, many of the slick animated transitions that people have come to associate with Flash can be accomplished without plug-ins at all, and in a way that preserves the benefits of HTML.
What about cross-platform compatibility? In general, the script.aculo.us visual effects work reliably across different browsers (Internet Explorer 6+ for Windows, Firefox, Safari, Konqeror, Camino, and, with a few exceptions, Opera). And because the animated effects are time-based (as opposed to frame-based) they work consistently on systems of different speeds. You might be wondering: just because visual effects are easy, does that mean they’re a good idea? Isn’t it just eye candy? And what does it have to do with Ajax, anyway?
The full answer to those questions will come in Chapter 6, but here’s the short one. More than just mere decoration, visual effects can be essential to providing a good user experience, especially in conjunction with Ajax. For more than 10 years, users have gotten used to the way the Web works, and Ajax undermines many of their expectations. For example, there’s a basic expectation that web pages are static, that they won’t change once they’re loaded. But in the last chapter, all the Ajax examples made changes to the page without reloading, which has the potential to become confusing. To address that, visual effects can provide cues that make the interface more natural and discoverable.
A word of caution: just like special effects in the movies, script.aculo.us effects are generally best when you don’t notice them—when they are subtle and unobtrusive, they and contribute something to the plot. Remember when desktop publishing arrived in the 1980s, and every neighborhood newsletter suddenly used 10 different fonts, because it could? If at all possible, try not to get similarly drunk on the power of script.aculo.us.
The script.aculo.us’ Effect object is where the magic resides. Let’s look at it. First, we’ll need an element to try our effects on, so add one to the top of the new
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Drag and Drop
The ability to directly manipulate on-screen objects is often taken for granted in desktop applications, but web interfaces have been slow to follow—largely due to the complex DOM manipulation it requires. script.aculo.us changes that equation, and provides surprisingly easy and powerful support for drag-and-drop interfaces. That means that web developers can decide to use drag and drop based primarily on usability concerns, rather than technical ones. As with visual effects, it’s important to remember that drag and drop is often not the best solution to an interface problem. But when it is, script.aculo.us makes it painless.
script.aculo.us provides a Draggable class that’s used to add draggability to DOM elements. To get started, create a new template file, draggables.rhtml. In it, add this:
<div id="dragDIV" class="green box">drag</div>
<%= javascript_tag "new Draggable('dragDIV')" %>
When the page is loaded (http://localhost:3000/chapter4/draggables), the JavaScript statement causes a new instance of the Draggable class to be created, tied to the given element ID. From then on, you can drag the element around the page. Notice how it becomes slightly transparent while it is dragged—it uses the same Opacity effect we explored earlier. The Draggable constructor takes an optional second parameter for options, which will be detailed later.
Rails provides the draggable_element helper to create draggables. Just like Draggable.initialize, the first argument is the ID of an element, and the second is a hash of options. For example:
<div id="helperDIV" class="green box">helper</div>
<%= draggable_element :helperDIV %>
The output of draggable_element is a <script> element with a new Draggable statement. If you just need the JavaScript statement without the <script> tags, use draggable_element_js instead. For example:
<div id="clickDIV" class="green box">
    <%= button_to_function "Make draggable",
         draggable_element_js(:clickDIV) %>
</div>
For usability, it’s often a good idea to change the cursor when it’s over a draggable element. The CSS cursor property makes it easy. For example:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Summary
This chapter introduced the major features of script.aculo.us—specifically, those features of the library that have corresponding Rails helpers. Those features fall into two main categories: visual effects and drag and drop. The library has even more to offer and is fully dissected in Chapter 11.
In the next chapter, we’ll explore the crown jewel of Ajax on Rails: Ruby-generated JavaScript (RJS).
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 5: RJS
If you picked up this book for the first time and skipped directly to this chapter, I don’t blame you. And if you’re the linear type and have read all the previous chapters, everything has been leading up to this: Ruby-generated JavaScript (RJS) is the capstone of Ajax in Rails.
In the last few chapters, practically all the Ajax examples have one thing in common: they work by receiving small snippets of HTML from the server and inserting them into the page. It’s a delightfully simple approach, and it gets a ton done with a minimum of abstraction overhead. After all, we’re building web applications, so everything will eventually become HTML anyway. Rails has a rich set of helpers for generating HTML, so why not simply render that on the server side and transfer it as is. But sometimes the simple approach isn’t sufficient—sometimes you need more flexibility.
The Rails solution is to return JavaScript instructions, instead of HTML data, to Ajax requests. The JavaScript is executed as it comes in, so it can do anything that’s possible from scripting—insert new content into the page, create visual effects, call methods from external JavaScript libraries—you name it. And you can include as many JavaScript statements as you need in one response, so it’s trivially easy to update a bunch of page elements at once. Try that with the standard link_to_remote :update => ... helper and you’ll quickly appreciate how valuable JavaScript can be.
The power of that simple idea—returning JavaScript to Ajax requests—can’t be overstated. Suddenly the server’s role in Ajax applications has gone beyond just providing data; now it participates in the client-side logic as well. Of course, there’s nothing Rails-specific about basic idea of returning JavaScript to Ajax requests; it could be implemented in any language or framework. What sets Rails apart from the rest is how the JavaScript is created.
The kicker is that instead of writing the JavaScript by hand, Rails generates it. That’s where RJS, Ruby-generated JavaScript, comes in. RJS is Ruby code that generates JavaScript code, which is sent as the result of an Ajax call. Whereas most actions render
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!