1. Technology
You can opt-out at any time. Please refer to our privacy policy for contact information.

AJAX With Sinatra

By

AJAX is a method to make requests to a web application without reloading the entire page that made the request. For example, if you were to click on an email message in a web mail application, the entire page doesn't reload. The email message is loaded and displayed in a div, but the rest of the page stays as it was. Using AJAX and a little bit of jQuery (a popular Javascript library that makes a lot of things here easy) you can make AJAX requests to your Sinatra web application very easily.

What is AJAX?

AJAX stand for Asynchronous Javascript and XML. In short, it's a way of updating just part of, or none of, a web page when making a request to a web application instead of reloading the entire page every time a link is clicked or a form is submitted. Using related Javascript techniques, you can also have buttons not attached to any form at all perform actions on the page.

On the client side, things can be quite a bit different. You're no longer simply spitting out HTML and when a form is submitted or a link clicked on you get a whole new page. Instead, you're using Javascript callbacks to make these HTTP requests and inserting the results into the page somewhere. It requires some knowledge of Javascript in order to use, but for the most part having just a cursory knowledge of Javascript will be sufficient for this article.

 

Though the name implies we'll be using XML, this is just a vestige of the technique's origin, and we'll be using JSON. JSON is a simpler markup language we'll use to transfer information between the Javascript frontend and Sinatra web application.

 

What is jQuery?

jQuery is a Javascript library that allows very simple manipulation of the DOM tree and an easy to use event-driven framework. Instead of long-winded Javascript to find the right element in the DOM tree with a specific ID and replace its content with something else, you can say very succinct things like $("#reset-button").html("Click me!") to change the reset button's text.

jQuery is an industry standard Javascript library. Open up the source for many of the major, minor or in between websites and you will see jQuery there quite often. If you're just getting into Javascript, you should probably be learning jQuery alongside it.

Making AJAX Requests

To get started, let's start with a fresh web application. It's root action serves a page with two buttons: Start and Stop. There's also a div on the layout with an ID of "message" we'll use for messages returned from the server. We'll also have two broken (for the time being) start and stop actions.


require 'sinatra'
require 'sinatra/reloader'

get "/" do
	haml :root
end

get "/start" do
	haml :start
end

get "/stop" do
	haml :stop
end

__END__
@@ layout
%html
	%head
		%title AJAX Example
	%body
		#message
		=yield

@@ root
%button#start Start
%button#stop Stop

@@ start
It has started

@@ stop
It stopped

Right now this doesn't do much of anything. It displays two buttons if you go to http://localhost:4567/start, but the buttons don't do anything. You can manually go to http://localhost:4567/stop or http://localhost:4567/, but they return complete pages with the intended messages (layout included). Let's start by making the buttons do something, even though the responses will be broken for the time being.

First, we need to get jQuery into our application. The standard way of doing this is to include jQuery directly from the jQuery CDN. So we'll add a line of Haml to our layout.


%html
	%head
		%title AJAX Example
		%script{:type => "text/javascript", :src => "http://code.jquery.com/jquery-2.1.0.min.js"}
	%body
		#message
		=yield

There's a bit of a Catch 22 when working with Javascript. Scripts are loaded often in the header or top of the page, but the elements they may refer to are often not loaded yet. So this is where our first jQuery callback comes in: the document ready callback. It's accessed like this.


$(document).ready(function() {
  // …
});

In here we'll put yet more callbacks. For each of the buttons, we'll add a click callback that's run when the button is clicked. We'll then use the jQuery ajax method to do the actual AJAX request and update the #message div. So this is what our Haml (and Javascript) looks like thus far.


__END__
@@ layout
%html
	%head
		%title AJAX Example
		%script{:type => "text/javascript", :src => "http://code.jquery.com/jquery-2.1.0.min.js"}
	%body
		#message
		=yield

@@ root
:javascript
	$(document).ready(function() {
		$("#start").click(function() {
			$.ajax( {url:"/start", success:function(result) {
				$("#message").html(result);
			}});
		});

		$("#stop").click(function() {
			$.ajax( {url:"/stop", success:function(result) {
				$("#message").html(result);
			}});
		});
	});
%button#start Start
%button#stop Stop

@@ start
It has started

@@ stop
It stopped

The javascript is loaded at the top of the body and may begin running at any time. The ready callback is called when the body is finished loading and the page is ready. Inside this callback, we define two other callbacks for start and stop, which are called when the buttons are clicked. The ajax method is called in these callbacks to perform the AJAX request and, on success, yet another callback is defined to replace the message div with the result from the AJAX request.

Phew, that's a mouthful, but it's not difficult to understand once you start playing with it. But if you click one of the buttons and examine the source code (using a DOM explorer, such as Chrome's "inspect element"), you'll see that an entire new HTML document is being returned and shoved into the div. We don't want that, so let's fix that in the controller.

What we really want is to return only the markup we want to go into the div. In other words, just don't render the template. Fixing this is simple, Sinatra gives us a method on the request object called xhr? which returns true if the XmlHTTPRequest header is set in the HTTP request (XmlHTTPRequest is the mechanism used to implement AJAX behind the scenes). If this is set, don't render the layout.


get "/start" do
	haml :start, :layout => (request.xhr? ? false : :layout)
end

get "/stop" do
	haml :stop, :layout => (request.xhr? ? false : :layout)
end

And there you have it. Once you get started, AJAX is very simple in Sinatra and jQuery. In the next article, we'll clean this up a bit, DRY it up and make it actually do something other than return a string.

  1. About.com
  2. Technology
  3. Ruby
  4. JRuby
  5. Automation of Windows using FFI
  6. AJAX With Sinatra

©2014 About.com. All rights reserved.