An Ajax client to a RESTful Rails web service

RESTful web services are the new buzzword when someone is talking about SOA or application integration, although REST isn’t something new (the Roy Fielding’s doctoral dissertation that defines it was published on 2000) it’s gaining traction now with people trying to run from the complexities of SOAP web services development . In a REST web service you are not offering “services” like functions or method calls, as they usually work in SOAP or plain RPC-over-HTTP services, your service provides “resources”, just like any web site that offers pages to it’s users.

Resources are the basic principle of RESTful web services, all operations and data in a REST application are made available by accessing resources. They must be addressable and uniquely distinguishable using an universal syntax for use in hypermedia links (like HTTP’s URLs, for example), so every resource must have it’s own unique address. A resource is anything that you would store, reference, retrieve or link to using hyperlinks, like a person’s information, a resource does not need to be something that is really stored on the server, it may be a result of an algorithm execution, like “all prime numbers until 50”, if it may be referenced or retrieved, it can be a resource.

All resources should also be accessible using a uniform interface to transfer state between the client and the server with a set of defined actions so all resources respond to the same “calls” in the same way, you won’t need to understand every resource operations, no resource will define an operation on it’s own, the only actions he can respond to are the ones defined by the common interface. Not every resource is able to respond to every “call” available on the common interface, some resources can only respond to some of the calls defined on the interface, but no resource will create it’s own call.

Once again taking HTTP as an example, the common interface are the set of HTTP defined methods, so if you are writing a REST service that runs over HTTP, your common interface are the HTTP’s methods (like GET, POST, PUT, DELETE, HEAD, OPTIONS ) and it’s response codes (like 200, 202, 400, 404, 500), so if you want to delete the resource that is on the URI “/games/1” you just need to send an HTTP request with the “DELETE” method to destroy it, and so on for every other method.

REST is not a technology in itself nor it is a standard like SOAP or WSDL, it’s a way to judge web appliction architetures, so if you folow the principles of REST you can make anything be “RESTful”, what we are going to do here is write an application that aims to be RESTful running over HTTP using the web browser as a REST client. If you try to think about it, a common web site is, usually, going in the RESTful way, it represents it’s contents as resources and links them, so you, driving your browser, is able to navigate from one page (a resource) to another, but most of our web sites don’t folow the rules of the unified interface, they just use GET and POST, because a browser can just do GET and POST HTTP requests, but they are on the right way.

We are going to write a Rails RESTful service, write an Ajax interface for the service and write some specs with RSpec to be sure that our application works correctly. Don’t be afraid if you don’t know RSpec yet, we will cover it briefly so you will be able to follow and even write your own specs, it’s pretty easy. If you don’t know anything about Ajax and JSON or are not comfortable with JavaScript yet, you should pick up a beginner’s tutorial before going on, I will use a lot of JavaScript and Ajax code with the Prototype and Scriptaculous libraries so you will need to know the basics before going on, you don’t need to be a master of Prototype or Scriptaculous, as I will be explaining and showing code, but you should at least take a look at a simpler tutorial.

So, you’re still a little confused about what is REST and what does it do? We will dig deeper on these concepts once they are presented over the course of the tutorial, so let’s start coding!

Our sample application is a gaming site, where the user can see, create, edit and remove games and also add the games he owns to an “owned games” list. You can follow this tutorial writing you own code or you can just follow looking at the sample code provided (which is easier to do). You can download the sample code here.

Setting up the environment

To follow this tutorial you need to have Rails 1.2.5 or newer, the “json” and the “rspec” gem. If you don’t have them, open a console and hit:


gem install rspec -y
gem install json -y

After installing them, create your Rails application:

rails rails_rest_tutorial

From now on, all commands should be done inside you Rails app directory.

After creating the application, you should copy all the folders under “vendor/plugins” from the sample application file to your “vendor/plugins” folder, so you don’t need to download them all again. After copying all files, run the following command to set up the RSpec files for your Rails app:

ruby script/generate rspec

Now let’s create the scaffolding code for our models. The scaffold that we will create is not the common scaffold for simple HTML forms, it’s the “resource” scaffold, hit on you console:

ruby script/generate scaffold_resource genre name:string description:text
ruby script/generate scaffold_resource platform name:string description:text
ruby script/generate scaffold_resource game name:string description:text platform_id:integer genre_id:integer
ruby script/generate scaffold_resource user login:string password:string

Before migrating the database, you should also use the 006 and 007 migrations available with the sample application, as they create the “games_users” link table and add some example data to help you play and run tests against your application.

These calls will generate all the scaffolding code we need to start our application, the greatest difference from these controllers to the common scaffold controllers are the URLs they will respond to and a new method call, the “respond_to” that enables a controller to answer with different formats, depending on what the client is asking. Let’s see the code of one of them:

Listing 1 – games_controller.rb

  # PUT /games/1 PUT /games/1.xml
  def update
    respond_to do |format|
      if @game.update_attributes(params[:game])
        format.html { 
          # ## should only display flash notice if this is a HTML request
          flash[:notice] = 'Game was successfully updated.'
          redirect_to game_url(@game)
        }
        format.xml  { head :ok }
        format.json { head :ok }
      else
        format.html { render :action => "edit" }
        format.xml  { render :xml => @game.errors.to_xml, :status => 400 }
        format.json { render :json => @game.errors.to_json, :status => 400 }
      end
    end
  end

As you might have noticed, the first difference is the “respond_to” method, it receives a block of code that will say what needs to be rendered depending on the format provided by the client. If the format is HTML, it will generate the corresponding HTML generated by the scaffold, if the format is XML it just returns a response with the “200” status to the client or an XML with the errors generated.The other difference is the HTTP method that is called and the URL that is generated, this “update” action is called when there is an HTTP “PUT” request for the URL “/games/1”, which means that someone is “putting” something in a resource that already exists, in this case is the resource identified by the URL “/games/1”.

This is where we start to see the “common interface” in action, as the common interface are the HTTP methods and response codes, all interactions with resources must be done using this interface. So, if I want to update the resource “/games/1” I will send a PUT request with the information that I want to update on the object, if I want to get the resource representation I will send a GET request and so on.

“What is the big deal here? it’s just plain old HTTP!”

As I said on the beginning, the principle of the common interface means that you don’t need to learn a new way to interact with every resource, so if I can interact with the “/games/1” resource with PUT, GET, DELETE, all other resources (the genres, platforms and users) will be available in the same way, and, especially, with the same behavior. A delete always deletes a resource, a put always updates a resource, a get always retrieves a resource representation, in a RESTful web service you will never see a “GET” that deletes a resource or a “HEAD” that updates a resource, because if something like this happens we won’t have a common interface at all.

Throughout our examples we will follow a simple guideline for resource URLs and method behaviours:

  • A GET on “/resources” (like “/games”) will return all resources of the type provided, if the request contains params they will be used to filter the query;
  • A GET on “/resource/id” or “/resource/id.format” (like “/games/1” or “/games/1.json”) will return the resource defined in the format specified (if it is available);
  • A POST on “/resources” will create a new resource with the params provided on the post body and return the URL for the created resource;
  • A PUT on “/resource/id” will update the identified resource with the params provided;
  • A DELETE on “/resource/id” will delete the identified resource;

Updating the controller code

In our application we will be doing Ajax calls to the server and we want the server to send responses as JSON encoded objects. If you know JavaScript, you already know JSON, it’s just an JavaScript object or an array of JavaScript objects, so our server should return JSON representations of the resources to our client when we specify the format as JSON.

Unfortunately, the controller generated by the scaffold_resource does not return JSON response, so we need to add a “json” option for every “respond_to” call on our controller actions. Before going to the code we need something else in our controller, as I have said before, the HTTP status codes are also part of the uniform interface of our RESTful service, so they need to be used to conform with the behaviors and responses of our service. Let’s see how we can use some of them:

  • 200 (Ok) – When everything runs fine, just return 200 to the client;
  • 201 (Created) – When the client does a POST and creates a new resource, the server should return 202;
  • 400 (Bad Request) – When validation fails or the client did not send enough information to the server, it should return a 400, indicating that the request was not accepted, this usually happens when the client sends data that the server interprets as invalid (as an incomplete form submission);
  • 401 (Unauthorized) – Used when the client has not provided credentials to access private data, this response code triggers the HTTP authentication mechanism in most HTTP clients;
  • 403 (Forbidden) – When a user tries to access sensitive information that he can not see or if he tries to make a change that he can not do, this status should be returned. If the user needs authentication to perform the action, you should return 401 (Unauthorized), 403 should be used only when the client, even if it’s authenticated, does not have the right to perform the operation over the resource (like trying to change an email of another user);
  • 404 (Not Found) – If the client requests a resource that does not exists, the server should return 404 as it would if the client tried to request a file that does not exists;

There are many others HTTP response codes, but these are the ones you will most commonly see and use in your applications.

The Games controller

Let’s see the how the code of our GamesController has changed and why it has changed:

Listing 2 – games_controller.rb

class GamesController  [ :show, :edit, :update, :delete ]
  
  # # GET /games GET /games.xml
  def index
    
    query = Game.query
    
    if params[:game]
      unless params[:game][:name].blank?
        disjunction = query.or
        params[:game][:name].split(' ').each do |i|
          i = "%#{i}%"
          disjunction.name_ilike(i)
          disjunction.description_ilike(i)
        end
      end
    
      query.genre_id_eq( params[:game][:genre_id] ) unless params[:game][:genre_id].blank?
      query.genre_id_eq( params[:game][:platform_id] ) unless params[:game][:platform_id].blank?
    end
    
    @games = query.find
    
    respond_to do |format|
      format.html # index.rhtml
      format.json { render :json => @games.to_json }
      format.xml  { render :xml => @games.to_xml }
    end
  end

  # GET /games/1 GET /games/1.xml
  def show
    respond_to do |format|
      format.html # show.rhtml
      format.json { render :json => @game.to_json }
      format.xml  { render :xml => @game.to_xml }
    end
  end

  # GET /games/new
  def new
    @game = Game.new
  end

  # GET /games/1;edit
  def edit
  end

  # POST /games POST /games.xml
  def create
    @game = Game.new(params[:game])

    respond_to do |format|
      if @game.save
        format.html { 
          # ## should only display flash notice if this is a HTML request
          flash[:notice] = 'Game was successfully created.'
          redirect_to game_url(@game)
        }
        format.xml  { render :xml => @game.to_xml, :status => 201, :location => game_url(@game) }
        format.json { render :json => @game.to_json, :status => 201, :location => game_url(@game) }
      else
        format.html { render :action => "new" }
        format.xml  { render :xml => @game.errors.to_xml, :status => 400 }
        format.json { render :json => @game.errors.to_json, :status => 400 }
      end
    end
  end

  # PUT /games/1 PUT /games/1.xml
  def update
    respond_to do |format|
      if @game.update_attributes(params[:game])
        format.html { 
          # ## should only display flash notice if this is a HTML request
          flash[:notice] = 'Game was successfully updated.'
          redirect_to game_url(@game)
        }
        format.xml  { head :ok }
        format.json { head :ok }
      else
        format.html { render :action => "edit" }
        format.xml  { render :xml => @game.errors.to_xml, :status => 400 }
        format.json { render :json => @game.errors.to_json, :status => 400 }
      end
    end
  end

  # DELETE /games/1 DELETE /games/1.xml
  def destroy
    Game.delete(params[:id])
    respond_to do |format|
      format.html { redirect_to games_url }
      format.xml  { head :ok }
      format.json { head :ok }
    end
  end
  
  private 
  
  def find_game
    if params[:format] == 'html' || params[:format].blank? || Game.exists?( params[:id] )
      @game = Game.find( params[:id] )
      yield
    else
      render :text => "Could not find any game with the given identifier => #{params[:id]}", :status => 404
    end
  end
  
end

As you can see, the code is dead simple, what we needed to do on the generated scaffold was mostly add a new “format.json { render :json => @game.to_json }” thanks to the Rails built-in support for JSON serialization. Although it is not as good as it should be, the serialization works fine for most cases (and Rails 2 will come with a better serialization mechanism, so you don’t need to worry about it) and if it does not work for you, just override the “to_json“ method.

There is something else to notice, the “flash” variable should not be used on RESTful services, because they should be stateless, the server should not maintain any state, even a state as simple as the flash variable and even if you did put anything on the flash, you wouldn’t have any way to make it reach your REST client, as the flash is not a resource.

The statelessness of RESTful services are an effect of passing all scoping information using the common interface, so in our case, a RESTful service running over HTTP, all information the server will need to perform it’s work should be passed on the URL, params, HTTP headers and cookies (cookies are something that should be used as little as possible on RESTful services ), the server should not save any state beyond the duration of the request.

The “index” action contains a call to a strange method, “query”, it’s a method added by the “criteriaquery” Rails plugin, if you want to learn more about it just look at the plugin’s read-me on “vendor/plugins/criteriaquery”. It simplifies the way you write queries, instead of writing a bunch of SQL and setting it’s parameters you can just create a “query” object and “build” you query, statement by statement (it’s the Builder pattern in action), as with “name_ilike()” that means that I want it to generate an “ilike” ‘where’ criteria with the specified value.

There is also another two common plugins being used, the “foreign_key_migrations” and “foreign_key_associations”, the migrations plugin automatically create foreign keys for you database tables if you give names like “associated_class_name_id” to you association columns, and the associations plugin automatically creates the associations for your objects if you follow the naming convention above. The plugin also creates properties for “has_and_belongs_to_many” associations for you objects if the association’s table name is the name of the two classes involved in alphabetical order, you shouldn’t write a Rails application without using these two plugins.

Also, if you compare with the code generated using the “scaffold_resource”, I have added a lot of HTTP response codes to the XML and JSON clients. As we should stick with our common interface, we should not return an HTTP 200 response with an error message when an error has occurred just because we want to show something pretty to the browser, a REST client is, usually, an automated client, so it should be easy for it to discover that there is something wrong and the easiest way to do this communicating with HTTP is using the HTTP response codes. If the server can’t find the resource requested by the client, the server just returns a 404 response with a message (as you can see on the “find_game” method, that is used as an “around_filter” for some methods), the server could also send error messages on the body of the response, in a format that the client is expecting, so if the client is accessing the resources using the JSON representations, the server should return error messages in JSON format.

The “games_url” and “game_url()” that you saw at the code, are methods generated automatically to generate a URL for the games resource, the first one generates the URL to the root resource, the other generates the URL to a specific resource.

The Users controller

The code of our users controller is simples because it does not need to perform all CRUD operations, it just needs to create a new user, load his game’s list, add a new game to the list and remove a game from the user’s games list, is does not need to show all users, delete or update a user’s information. Let’s see it’s code:

Listing 3 – The Users controller

class UsersController < ApplicationController
  
  requires_authentication :using => :authenticate, 
    :only => [ :show_current_user, :remove_game, :add_game ],
    :realm => 'RESTful Ajax client tutorial',
    :error_msg => 'Could not match your credentials',
    :logout_on => :logout
  
  around_filter :validate_current_user, :only => [ :remove_game, :add_game ]

  # POST /users POST /users.xml
  def create
    @user = User.new(params[:user])

    respond_to do |format|
      if @user.save
        format.html { 
          flash[:notice] = 'User was successfully created.'
          redirect_to user_url(@user)
        }        
        respond_to_with do |symbol|
          render( symbol => @user.send( "to_#{symbol}" ), 
            :location => "#{user_url( @user )}.#{symbol}", 
            :status => 201  )
        end
      else
        format.html { render :action => "new" }
        respond_to_with do |symbol|
          render( symbol => @user.errors.send( "to_#{symbol}" ), :status => 400 )
        end
      end
    end
  end
  
  def show_current_user
    respond_to_with do |symbol|
      render( symbol => current_user.send( "to_#{symbol}" ) )
    end
  end
  
  def remove_game
    User.remove_game( params[:user_id], params[:game_id] )
  end
  
  def add_game
    User.add_game( params[:user_id], params[:game_id] )
  end
  
  private
  
  def validate_current_user
    if current_user.id == params[:user_id].to_i
      yield
      head :ok
    else
      head :forbidden
    end
  end
  
end

One of the new things you will find on this code is the “requires_authentication” method, it is provided by a Rails plugin that enables HTTP authentication, so when the browser tries to make a request to a secured resource and does not send the right credentials, the server just sends him an 401 response, meaning that he is not authorized to view the contents of the resource. The plugin handles all this plumbing automatically, so you just need to write the code to authenticate the user using it’s username and password (in our example the “authenticate()” is located on the ApplicationController class, but you can place it wherever you like).

Another item to take notice if the “validate_current_user” method, the server should only make changes to a user’s games list if the user requesting the changes is the same where the chances are being made, a user should not be able to change another user’s account or games list. If a user tries to alter another user’s information it should receive an 403, or maybe even a 404. When you send an answer of 403 to a client that is trying to make a change to a resource, you automatically “say” that the resource exists, it just is not available, but when you return a 404 the client understands that the resource does not even exists, and this could be a better approach if you don’t want any crackers trying to discover the users that exists in your database changing the URL.

The “respond_to_with” method that you see is just an utility that I created to simplify writing the response to RESTful clients accessing the service with XML and JSON. As the only thing that changed between one method and the other was the “to_xml” or “to_json” I’ve created a method that yields to a block passed as parameter passing the format specified as a symbol, so the block can just use the symbol on the method call (as I have used on the code you see on the controller), there is no need to write the same block to XML and JSON responses if the only thing that changes is the “xml” or “json” call.
The method implementation is found on the ApplicationController below:

Listing 4 – The Application controller

# Filters added to this controller apply to all controllers in the application.
# Likewise, all the methods added will be available for all controllers.

class ApplicationController < ActionController::Base
  FORMATS = &#91; :xml, :json &#93;
  # # Pick a unique cookie name to distinguish our session data from others'
  session :session_key => '_rails_rest_tutorial_session_id'
  
  protected
  
  def respond_to_with
    respond_to do |format|
        FORMATS.each{ |symbol|
            format.send( symbol ){
              yield( symbol )
            }
        }    
    end
  end
  
  def authenticate( username, password )
    @current_user = User.authenticate( username, password )
  end
  
  def current_user
    @current_user
  end
  
  def logout
    render :text => 'You are out of the application'
  end
  
end

As most of the User controller’s methods are just calling methods on our User model object, let’s see the model’s code:

Listing 5 – The User model

class UsersController < ApplicationController
  
  requires_authentication :using => :authenticate, 
    :only => [ :show_current_user, :remove_game, :add_game ],
    :realm => 'RESTful Ajax client tutorial',
    :error_msg => 'Could not match your credentials',
    :logout_on => :logout
  
  around_filter :validate_current_user, :only => [ :remove_game, :add_game ]

  # POST /users POST /users.xml
  def create
    @user = User.new(params[:user])

    respond_to do |format|
      if @user.save
        format.html { 
          flash[:notice] = 'User was successfully created.'
          redirect_to user_url(@user)
        }        
        respond_to_with do |symbol|
          render( symbol => @user.send( "to_#{symbol}" ), 
            :location => "#{user_url( @user )}.#{symbol}", 
            :status => 201  )
        end
      else
        format.html { render :action => "new" }
        respond_to_with do |symbol|
          render( symbol => @user.errors.send( "to_#{symbol}" ), :status => 400 )
        end
      end
    end
  end
  
  def show_current_user
    respond_to_with do |symbol|
      render( symbol => current_user.send( "to_#{symbol}" ) )
    end
  end
  
  def remove_game
    User.remove_game( params[:user_id], params[:game_id] )
  end
  
  def add_game
    User.add_game( params[:user_id], params[:game_id] )
  end
  
  private
  
  def validate_current_user
    if current_user.id == params[:user_id].to_i
      yield
      head :ok
    else
      head :forbidden
    end
  end
  
end

We have created the “add_game” and “remove_game” methods add and remove games from a user’s games list without having to load the user or the game from the database, this way we avoid making unnecessary queries to the database. Also, the “has_game” method guarantees that there is no bad SQL coming, as it transforms the parameters in integer numbers. As the “games_users” table is not an ActiveRecord object, we had to use the database connection directly and send the statements through it.

Another thing to take notice is the overriding of the “to_json” method. The current “to_json” method on ActiveRecord objects just reads all properties and transforms them in a JavaScript object, so, in our user model it would just send the user’s password over the wire, which is not something intelligent, so we’ve overridden the method using the JSON gem API directly, sending only the information that we need, that is the user’s login, id and games list.

Before writing the client application, we also need to make some changes on the routing mechanism, let’s see how our routes.rb file should be:

Listing 6 – Application rouces

ActionController::Routing::Routes.draw do |map|
  
  map.connect 'current_user.:format', :controller => 'users', :action => 'show_current_user'
  map.connect( 
    'users/:user_id/games/:game_id.:format', 
    :controller => 'users', 
    :conditions => { :method => :delete },
    :action => 'remove_game' )
  map.connect( 
    'users/:user_id/games/:game_id.:format', 
    :controller => 'users', 
    :conditions => { :method => :put },
    :action => 'add_game' )
  
  map.resources :users

  map.resources :games

  map.resources :platforms

  map.resources :genres

  # The priority is based upon order of creation: first created -> highest priority.
  
  # Sample of regular route:
  # map.connect 'products/:id', :controller => 'catalog', :action => 'view'
  # Keep in mind you can assign values other than :controller and :action

  # Sample of named route:
  # map.purchase 'products/:id/purchase', :controller => 'catalog', :action => 'purchase'
  # This route can be invoked with purchase_url(:id => product.id)

  # You can have the root of your site routed by hooking up '' 
  # -- just remember to delete public/index.html.
  # map.connect '', :controller => "welcome"

  # Allow downloading Web Service WSDL as a file with an extension
  # instead of a file named 'wsdl'
  map.connect ':controller/service.wsdl', :action => 'wsdl'

  # Install the default route as the lowest priority.
  map.connect ':controller/:action/:id.:format'
  map.connect ':controller/:action/:id'
  map.connect '', :controller => 'main', :action => 'start'
end

The “map.resources” are the special calls that makes our RESTful controllers work with real RESTful URLs and the common interface, responding differently for different methods in the same URL.

Writing the client application

Now that we have written the server code, it is time to write the client. Our client is a simple HTML page that makes Ajax calls to our REST service using the Prototype API, this client must be able to show a games list, search games, show game information and if the user is logged in create and edit games and see it’s owned games list, adding and removing games from it. All page fragments that you will see here are part of the same page, I have separated them in partials to make it easier to change and understand the code, but at the end they are all included as partials to the main page and that’s why many of them are marked with “display:none”, so they will not show on the page until it is necessary.

Let’s start with the simpler parts, showing the games list and the game information. Our games list is just a simple HTML Table that will be filled with the games filtered by the user’s search form. The code is the following:

Listing 7 – Games list table

    <table style="display:none;">
      <thead>
        <tr>
          <th class="first"><strong>game</strong> title</th>
          <th><strong>platform</strong></th>
          <th><strong>genre</strong></th>
          <th><strong>actions</strong></th>
        </tr>
      </thead>
      <tbody>
      </tbody>
    </table>
    

You should keep the “id” attribute on the code because it will be necessary on our JavaScript code, but you can change styles, classes and everything else. As you can see, there is nothing new or strange about it. After the games list, we need to create the games search form, to perform searches on the games list, let’s see how the code should look like:

Listing 8 – Games search form

   <div>
     <form>
       <table>
         <tbody>
           <tr>
             <td>Name/Description:</td>
             <td> &lt;%= text_field_tag 'game[name]' %&gt; </td>
           </tr>
           <tr>
             <td>Genre:</td>
             <td> &lt;%= generate_genres_select genres %&gt; </td>
           </tr>
           <tr>
             <td>Platform:</td>
             <td> &lt;%= generate_platforms_select genres %&gt; </td>
           </tr>
         </tbody>
       </table>
       <br />

</form>
   </div>

The form is just a common HTML form, it’s “onsubmit” event calls a JavaScript function that will make the search in our REST service (and that we will see soon), the only strange thing is the “generate_genres_select” and “generate_platforms_selelect” methods, these methods generate HTML selects for our form and they are defined on the MainHelper, the helper for the controller that will send our HTML file to the client. Let’s see the controller and helper code:

Listing 9 – The Main controller

class MainController < ApplicationController

  def start
    @title = 'RESTful JavaScript client'
    @platforms = Platform.find :all
    @genres = Genre.find :all
    render :action => 'start', :layout => false
  end
  
end

Listing 10 – The Main helper

module MainHelper
  
  def generate_select ( name, options_collection, prompt, html_options = {} )
    options = "<option value=''>#{prompt}</option>\n" + 
      options_from_collection_for_select(options_collection, "id", "name");
    
    select_tag name, options, html_options
  end
  
  def generate_genres_select( genres, html_options = {} )
      generate_select 'game[genre_id]', genres, 'Select a genre', html_options
  end

  def generate_platforms_select( platforms, html_options = {} )
      generate_select 'game[platform_id]', platforms, 'Select a platform', html_options
  end
  
end

As you can see, the code is pretty simple, the main controller just loads two instance variables (the genres and platforms list) and renders our Ajax client page, these variables will be used a lot on our page, so they will be cached and the client will not keep requesting the genres and platforms information to the server, just the games.

Now that we have a search form and a place to put the search results, let’s write the code that sends the search to the server:

Listing 11 – Using Prototype to make an Ajax request

    var platforms = &lt;%= platforms.to_json %&gt; ;
    var genres = &lt;%= genres.to_json %&gt; ;
    var currentUser = null;

function findById( id, items ) {
           for ( var index = 0, len = items.length; index < len; index++) {
               if ( items&#91;index&#93;.attributes.id == id ){
                   return items&#91;index&#93;;
               }
           }
       }

var gameItemTemplate = new Template(
                 "<tr class='#{cssClass}'>"
               + "<td>#{name}</td>"
               + "<td>#{platform}</td>"
               + "<td>#{genre}</td>"
               + "<td>"
               + "<a href='#'>Show</a> - "
               + "<a href='#'>Edit</a> - "
               + "<a href='#'>Delete</a> <br /> "
               + "</td>"
               + "");

function findGenre( id ) {
           return findById( id, genres);
       }

function findPlatform( id ) {
           return findById( id, platforms);
       }

/** takes a game from a Rails returned JSON and copies it to a simpler
       representation**/
       function toGame( game ) {
          return {
                id: game.attributes.id,
                name: game.attributes.name,
                description: game.attributes.description,
                platform_id: game.attributes.platform_id,
                platform: findPlatform( game.attributes.platform_id ).attributes.name,
                genre_id: game.attributes.genre_id,
                genre: findGenre( game.attributes.genre_id ).attributes.name
          };
       }

/** generates a string with a list of games **/
       function generateGamesList( games ) {
           var resultList = "";
           for (var index = 0, len = games.length; index < len; ++index) {
               game = toGame( games&#91;index&#93; );
               if ( (index % 2) == 0 ) {
                   game.cssClass = "rowA";
               } else {
                   game.cssClass = "rowB";
               }
               resultList = resultList + gameItemTemplate.evaluate( game ) ;
           }
           return resultList;
       }

function updateGamesList( games ) {
           $('gamesListTableBody').innerHTML  = generateGamesList( games );
           new Effect.Appear( 'gamesListTable', { duration: 1.0, queue: "end" } );
       }

/* executes the search based on the form parameters */
       function searchGames() {
           new Effect.Fade( 'gamesListTable', { duration: 1.0 } );
               new Ajax.Request( '' ,
                         { method: 'get',
                           parameters: $( 'gamesSearchForm' ).serialize( true ),
                           onSuccess: function( transport ){
                              updateGamesList( transport.responseText.evalJSON() );
                           }
                         });

}

&#91;/sourcecode&#93;

It’s a big bunch of code, so let’s get to it in parts, starting from where everything starts, that is the “searchGames()” function. When this function is called, it creates an Scriptaculous effect that fades the table and makes it disappear from the page (it’s just to make the user say “Ooooohhh!”, it has no practical use beyond show the user that something is being done), then an Ajax.Request object is created, this is where the real action is, this method sends a request to the “/games.json”, that is the “index” method on our GamesController, the controller returns the search results to the client, a JSON encoded array of Game objects.

Using Prototype most of the plumbing code is unnecessary, I did not even had to create the query parameters or load anything from the form, I just did “serialize( true )” on the form instance (the “$()” Prototype method is equivalent to a call to “document.getElementById()” but before returning the object, it makes some chances and adds more methods and capabilities, like the serialize() method on form objects, this method creates a hash with the names and values of the objects on the form).

If our server really returns a 200 response, the function you passed to the “onSuccess” handler is called, in our case, it just evaluates the JSON returned and calls another function, the “updateGamesList()”. This function calls the “generateGamesList()” that creates a string result with the objects on the games JSON array to populate the table. We first flatten the game object, load it’s genre and platform names from the ones taken from the MainController (the objects are maintained as global variables, both genres and platforms) and passes it to the Prototype Template object created with a string that generates a table row with the game information. This template object is very handy in situations like this, where you need to generate complex HTML.

As you can see from the template, we have already added some events to view, edit and remove a game, so let’s implement these callbacks, starting with the view game:

<strong>Listing 12 – Game information panel</strong>

   <div style="display:none;">
     <h2><strong>Game</strong> information</h2>
     <table>
       <tbody>
         <tr>
           <td>Name:</td>
           <td>#</td>
         </tr>
         <tr>
           <td>Genre:</td>
           <td>#</td>
         </tr>
         <tr>
           <td>Platform:</td>
           <td>#</td>
         </tr>
         <tr>
           <td>Description::</td>
           <td>#</td>
         </tr>
       </tbody>
     </table>
     <span></span>
     <a href="#" mce_href="#">Back to games list</a>
</div>

This panel shows the complete game information, with it’s description, it is the simpler panel that we have here because it just shows the information. The span tag added at the end of the code is a placeholder for a future functionality that we will see when we reach the user’s games list and after it there is a link with a function that takes the user back to the games search form. Again, you should not change the tags “id” value, because they will be used throughout the JavaScript code. Let’s see the JavaScript code needed to perform this operation:

Listing 13 – Game information scripts

   var addToMyGamesLinkTemplate = new Template(
               "<a href='#'>Add to my games</a> - " );

/** hides a panel and them shows the other**/
       function changePanels( fromPanel, toPanel) {
           new Effect.BlindUp( fromPanel, { duration: 0.5 } )
           new Effect.BlindDown( toPanel, { duration: 0.5, queue: "end" } )
       }

function executeAjaxEval( url, _method, _function ) {
               new Ajax.Request( url ,
                         { method: _method,
                           onSuccess: function( transport ){
                               _function( transport.responseText.evalJSON() )
                           }
                         });
       }

/* loads a game information and shows it to the user */
       function loadGameForGameInfo( id ) {
           executeAjaxEval(
                   "/" + id + ".json",
                   "get",
                   function( result ) {
                       game = toGame( result );
                       $('gameNameCel').innerHTML = game.name;
                       $('gameGenreCel').innerHTML = game.genre;
                       $('gamePlatformCel').innerHTML = game.platform;
                       $('gameDescriptionCel').innerHTML = game.description;
                       if ( currentUser != null ) {
                           $('addToMyGamesLink').innerHTML =
                               addToMyGamesLinkTemplate.evaluate( game );
                       }
                       changePanels( 'searchAndGamesListPanel', 'gameInfoPanel' );
                   } );
       }

As you can see, there is not much to be done, the first thing is the “changePanels()” that hides an object and shows the other using the BlindUp and BlindDown Scriptaculous effects (one thing to notice here is the ‘queue: “end”’ parameter passed on the second effect, it instructs Scriptaculous to put the second effect on a queue waiting for the other events, so they always happen one after another and not concurrently).

The “loadGameForGameInfo()” function makes a request to a game resource, fills the game info table that we say before and makes a test, if there is a currently logger user, it adds a link to make the user be able to add the game to it’s games list, it there is no user logged in it just does not add the link.

After loading the game to show it’s information, we can load a game to edit it’s information, so let’s see the game edit form:

Listing 14 – Edit game form

   <div style="display:none;">
     <h2><strong>Game</strong> edition</h2>
     <form>
       <table>
         <tbody>
           <tr>
             <td>Name:</td>
             <td>  &lt;%= text_field_tag 'game[name]', nil, :id => 'gameName' %&gt; </td>
           </tr>
           <tr>
             <td>Genre:</td>
             <td>  &lt;%= generate_genres_select genres, :id => 'gameGenre' %&gt; </td>
           </tr>
           <tr>
             <td>Platform:</td>
             <td>  &lt;%= generate_platforms_select platforms, :id => 'gamePlatform' %&gt; </td>
           </tr>
           <tr>
             <td>Description:</td>
             <td>  &lt;%= text_area_tag 'game[description]', nil, :id => 'gameDescription' %&gt; </td>
           </tr>
         </tbody>
       </table>

</form>
     <a href="#" mce_href="#">Back to games list</a>
   </div>

Nothing new here, just some common Rails form tags and our methods to generate the genres and platforms HTML selects, the real magic is on the JavaScript code:

Listing 15 – Edit game scripts

       function fromGameFormToSearchPanel() {
           changePanels( 'gameFormPanel', 'searchAndGamesListPanel');
           $( 'editGameForm' ).reset();
       }

function selectOption( selectName, value ) {
           select = $( selectName );
           for ( var index = 0, len = select.length; index < len; index++ ) {
               if ( select.options&#91;index&#93;.value == value ){
                   select.options&#91;index&#93;.selected = true;
                   break;
               }
           }

}

/* populates the game form */
       function loadGameForEdit( id ) {
           executeAjaxEval(
                   "/" + id + ".json",
                   "get",
                   function( result ) {
                       game = toGame( result );
                       $('gameId').value = game.id;
                       $('gameName').value = game.name;
                       $('gameDescription').value = game.description;
                       selectOption( 'gameGenre', game.genre_id );
                       selectOption( 'gamePlatform', game.platform_id );
                       changePanels( 'searchAndGamesListPanel', 'gameFormPanel' );
                   } );
       }

/* submits the game for, creating a new game or updating an existing game */
       function submitGameForm() {

params = $( 'editGameForm' ).serialize( true );
           _method = '';
           url = '';

if ( $('gameId').value.blank() ){
               _method = 'post';
               url = '';
           } else {
               _method = 'put';
               url = '/' + $('gameId').value + '.json' ;
           }
           new Ajax.Request( url ,
                   { method: _method,
                     parameters: params,
                     onSuccess: function( transport ){
                       searchGames();
                     }
                   });

}

&#91;/sourcecode&#93;

The “selectOption” function is just an utility to select the game platform or genre on the HTML selects, he “loadGameForEdit()” is just like the “loadGameForGameInfo()”, just makes a request for a game and fills out the form with the returned information, so these two are mostly plumbing, the real action is at the “submitGameForm()” function. This function takes the form parameters and sends a request to the server to update or even to create a new game, but how do we do that?

As you might have noticed, the form contains a hidden field with the “gameId” ‘id’, so when a game is loaded for edition, this field is filled with the game id attribute, is the game is a new game, this field remains blank, so we can use the same form to add new games and to edit currently available games. So, why am I doing that test if the value exists on the method? Because if I’m going to create a new game, I should make a POST request with the values to the “/games” resource, if I’m going to update a game I should make a PUT request to the “/games/game_id” resource with the data I want to update. Also, if everything runs fine I automatically update the games list table running a search in background.

Now that we can create a new game, edit a currently available game the only thing that is missing is the delete game function, to let’s do it!

There is no HTML on this one, just implementing the event function that we defined on the game row template:

<strong>Listing 16 – Deleting a game</strong>

       /* deletes a game from the database */
       function deleteGame( id ) {
           new Ajax.Request( '/' + id + '.json' ,
                   { method: 'delete',
                     onSuccess: function( transport ){
                       gameId = "game_" + id;
                       new Effect.Fade( gameId, { duration: 1.0 } );
                       $( gameId ).remove();
                     }
                   });
       }

This one was easy huh?Nothing special with this one, it just sends a DELETE request to our resource, fades the table row and at the end removes it from the page. You should NEVER forget to remove the item from the page, if you just use the fade effect the row will just be invisible but it will still be there and will probably be a source of memory leaks and strange behavior to your application, so always remove something that you won’t need anymore.

The user’s place

We’ve written a lot of code to the games, so let’s write some code for the user, the first thing is loading the user and games list, as this is sensitive information we will use authentication, so no one beyond the user will be able to see it’s games list. This action will also be used as your “login” procedure, so when the user clicks on the login button, the page will try to load it’s game information and it will need do provide credentials. Let’s see our login page:

Listing 17 – Login

   <div>

<h3><strong>login</strong> to your account</h3>
     <div class="content">
       <p>Already a member? <a href="#" mce_href="#">Login!</a></p>
     </div>

<h3><strong>register</strong> for an account</h3>
     <div class="content">
       <p>Not a member yet? Create your account right now!</p>
       <br />
       <form>
         <p>Username: &lt;%= text_field_tag 'user[name]'%&gt; <br/>
           Password: &lt;%= password_field_tag 'user[name]'%&gt;
         </p>
         <br />
          <p> &lt;%= submit_tag 'Register'%&gt;  </p>
       </form>
       <p></p>
     </div>

</div>

Again, there is nothing special on this page, let’s see the functions that it is calling:

Listing 18 – Users registration and login

       function generateMyGamesList( games ){
           var resultList = "";
           for (var index = 0, len = games.length; index < len; ++index) {
               resultList = resultList + myGameTemplate.evaluate( games&#91;index&#93; ) ;
           }
           return resultList;
       }

/* authenticates the user */
       function authenticate() {
           new Ajax.Request( 'current_user.json' ,
                   { method: 'get',
                     onSuccess: function( transport ){
                       currentUser = transport.responseText.evalJSON();
                       $( 'myGamesList' ).innerHTML = generateMyGamesList( currentUser.games ) ;
                       changePanels( 'registerUserPanel', 'loggedUserPanel');
                       $( 'usernameCel' ).innerHTML = currentUser.login;
                     }
                   });
       }

function registerUser() {
           new Ajax.Request( '' ,
                   { method: "post",
                     parameters: $('registerUserForm').serialize(true),
                     onSuccess: function( transport ){
                       $('registerUserMessage').innerHTML = 'The user was registered succesfully';
                       authenticate();
                     }
                   });
       }

&#91;/sourcecode&#93;

This code is not different of what he have already seen, the “generateMyGamesList()” function just creates a big string using the template defined at the “myGameTemplate” object, the authenticate method loads the user and games list information and puts the user returned as the current user on the page.

After all this, the only thing that is missing is adding and removing games from the user’s games list, let’s see the scripts that perform this work:

<strong>Listing 19 – Adding and removing games from the user’s list</strong>

       /* reloads the 'myGamesList' */
       function loadMyGames() {
           new Effect.Fade( 'myGamesList', { duration: 1.0 } );
           new Ajax.Request( 'current_user.json' ,
                   { method: 'get',
                     onSuccess: function( transport ){
                       currentUser = transport.responseText.evalJSON();
                       $( 'myGamesList' ).innerHTML = generateMyGamesList( currentUser.games ) ;
                     },
                     onComplete: function( transport ) {
                       new Effect.Appear( 'myGamesList', { duration: 1.0, queue: "end" } );
                     }
                   });    }/* adds a game to a users selection of games */
       function addToMyGames( gameId ) {
           url = '/' + currentUser.id + '/games/' + gameId + '.json';
           new Ajax.Request( url ,
                   { method: 'put',
                     onSuccess: function( transport ){
                       loadMyGames();
                     }
                   });
       }/* removes a game from the user's selection of games */
       function removeMyGame( gameId ) {
           url = '/' + currentUser.id + '/games/' + gameId + '.json';
           new Ajax.Request( url ,
                   { method: 'delete',
                     onSuccess: function( transport ){
                       id = "my_game_" + gameId;
                       new Effect.Fade( id, { duration: 1.0 } );
                       $( id ).remove();
                     }
                   });

}

The first function just reloads the games list, the second, “addToMyGames()” sends a PUT request to the URL “/users/:user_id/games/:game_id” meaning that the game with the “:game_id” should be added to the user’s games list. So why PUT and not POST? Because we should always use PUT when the know the URL of the generated resource, we should only use POST if we don’t know the URL that will be generated by the resource. Then, on the “removeMyGame()” sends a DELETE request to the same URL to remove the relationship.

And that’s about all the code our RESTful Ajax client will need to work. You should check example code to see how everything is was glued together, but before going to the conclusions there is something else to be done, write some specs!

Writing the specs for our controllers

If you were really doing this in a real world application, the first thing you should do is writing tests or specs proving that your code does not work and then writing code enough to make the tests and specs pass, this is what is usually called Test- (in the case of tests) or Behaviour- (in the case of specs) Driven Development. But as we’re just going thought a tutorial about a RESTful service and it’s Ajax client, we’re just going to introduce RSpec and how to write specifications to prove that your code really does what it says it does, for now let’s define RSpec as a framework where we can state what our application should do and run this definition against our code to see if it really works the way we stated (you can find more detailed explanations and tutorials at the end of this article).

Let’s start with a simple spec stating that “The games controller should should respond with an 404 status if the resource could not be found”, the spec we would write would look like something like the following:

Listing 20 – Starting to write the games controller specs

   describe GamesController do

it 'should respond with an 404 status if the resource could not be found' do
       Game.stub!( :find ).and_return( nil )
       [ :show, :edit, :update, :delete ].each do |action|
         [ 'xml', 'json' ].each do |format|
           get action, :id => '1', :format => format
           response.response_code.should == 404
         end
       end
     end

end

A spec starts with a “describe” telling who is being specified, it could have been a simple string, but the most common is using a class name. A definition starts with an “it”, every it is something that the object in question should do, it’s one of it’s specified behaviours. So, to make the controller respond with a 404 we need to make him search in the database for a row that does not exists, right?

Wrong!

We just need to stub out the “find()” method on the Game model class and make it return “nil” for our example, this way the controller will think that there is no resource and generate a 404 response. The code that does just that is the exactly on the first line of our example:

           Game.stub!( :find ).and_return( nil )
   

First, the “stub!” method replaces the find method implementation and then makes it returns the value passed as parameter to the “and_return” method. It could not be simpler!

Then we execute a “get” to the controller, making it run with our parameters and see if our spectation was met:

           response.response_code.should == 404
   

If the response is not a 404, an error is thrown and a report is generated. So you can go on writing your own specs and looking if you application is really working as “spected”.

You can see more spec samples on the following code sample:

Listing 21 – GamesController sample specs

# 
# To change this template, choose Tools | Templates and open the template in the
# editor.
 
require 'games_controller.rb'

describe GamesController do
  
  before(:each) do
    @game = mock 'game' 
    @game.stub!(:new_record?).and_return( false )
    @game.stub!(:save).and_return( true )
    @game.stub!( :to_json ).and_return( '' )
    @game.stub!( :to_xml ).and_return( '' )
    
    @errors = mock 'errors'
    @errors.stub!(:to_xml).and_return('')
    @errors.stub!(:to_json).and_return('')
    
    @game.stub!(:errors).and_return(@errors)
    
    Game.stub!(:new).and_return(@game)
  end

  it 'should respond with a common HTML response when there is no format' do    
    games_list = mock 'games_list'
    Game.should_receive(:query).and_return( games_list )
    games_list.should_receive( :find ).and_return( games_list )
    get :index
  end
  
  it 'should generate a flash message if the format is HTML' do
    get :create
    flash[:notice].should_not be_blank
  end
  
  it 'should not generate a flash message if the format is not html' do
    @game.stub!( :update_attributes ).and_return( true )
    Game.stub!(:find).and_return(@game)
    [ :create, :update ].each do |action|
      [ 'xml', 'json' ].each do |format|
        get action, :format => format, :id => '1'
        flash[:notice].should be_blank
      end
    end
  end
  
  it 'should respond with an 400 status if validation fails on creating a game and format is not html' do
    @game.stub!( :save ).and_return( false )
    @game.stub!( :update_attributes ).and_return( false )
    Game.stub!(:find).and_return(@game)
    [ :create, :update ].each do |action|
      [ 'xml', 'json' ].each do |format|
        get action, :format => format, :id => '1'
        response.response_code.should == 400
      end
    end
  end
  
  it 'should respond with an 404 status if the resource could not be found' do
    Game.stub!( :find ).and_return( nil )
    [ :show, :edit, :update, :delete ].each do |action|
      [ 'xml', 'json' ].each do |format|
        get action, :id => '1', :format => format
        response.response_code.should == 404
      end
    end
  end
  
end

Is our application really RESTful?

To be sure that our application is really folowing the RESTful way, we have to take a look at the principles that make an application RESTful (as defined on “RESTful Web Services“), thet are addressability, statelessness, connectedness and the uniform interface.

The principle of addressability means that a web service must espose it’s data, algorithms or whatever it does as resources and every resource is uniquely identifiable. Also, every representation of a resource must have it’s own URI, so a XML representation of a resource must have it’s own representation ( like in “/games/1.xml” for the resource “/games/1”). The representation might be selected using HTTP headers (like ‘Accept’ headers) but they must not be the only way to do this. In our example, all resources are uniquely identifiable and their different representations also have their own URIs, so we passed on this one.

Before going to the principle of statelessness, we need to differentiate application state from resource state. The application state is the information about what the user is doing in the application, like where he is now, what he is seeing and even it’s credentials, if the application requires them. Resource state is information about resources, like the database rows that contains the data. The principle of statelessness says that an RESTful service is stateless if it does not stores any application state, it should never store any data about who is requesting a resource beyond the duration of the request, every request should be as isolated as possible. When you don’t store application state, the only state that you need to store is the resource state, so you can have a lot of web servers serving your resources, without worring about clustering or anything like that, just put a load balancer and you’re done. In our example, the application does not hold any particular application state (well, the flash is used when the client is a web browser, but we are not using it, are we?) and even the user’s credentials are sent at every user’s request, one more down.

The principle of connectedness says that the resources should link to each other. If I have a game that as a platform and a genre, the game representation should point to the platform and genre representations. When using a well connected service, the client is able to make a path through the application just by following hyperlinks and filling forms, when the service is not well connected the client will have to build the URLs by itself, and if someday the URL format changes the code that builds the URL wiil have to be rewritten. Our service is far from being well connected, their representations never link to each other and our client is always building the URLs based on it’s knowledge about the way the service work, so our service is not well connected.

The last principle is the uniform interface, and as we have been talking about this through the whole tutorial, you already know what is it. Our application follows the uniform interface and althought it breaks it in some Ajax calls, it is not a problem with the application, but a quirk of our client.

Conclusion

So, as you saw following this tutorial, writing a RESTful service using Rails is dead simple, most of the plumbing is already done for you (like routing URLs) but we still have some caveats that need to be addressed. The first one is the response codes, the scaffold generator is not sending the response codes correctly, it’s sending a 200 response with an error message, when it should send a 400, and this is not a behavior that a REST client will be able to handle. If there is something going wrong, this should be on the status of the response and not only on it’s body.

Another very important thing to notice is that a browser, even using Ajax, can only do GET and POST requests, our Ajax client never sent an DELETE request, what it did was add a “_method” parameter to the request with the name of the method you wanted it to do and Rails is intelligent enough to route the call to the right method, even if this is a POST. So, your Ajax client is not completely RESTful, but it did the job nonetheless because Rails helped it a little bit.

In our example, we never did any special treatment to error conditions, we guessed that everyting would run fine, but the real world is quite different than that. You should always expect that something will go wrong and be ready to make your application fail gracefully showing a message to your client.

References

Agile Web Development With Rails. David Thomas and David Heinemeier Hansson. Pragmatic Bookshelf.

RESTful Web Services. Leonard Richardson and Sam Ruby. O’Reilly.

Architectural Styles and the Design of Network-based Software Architectures. Roy Fielding. University of California, Irvine.

RESTful Rails Development. Ralf Wirdemann and Thomas Baustert. b-simple.

Behaviour Driven Development: Part 1Part 2Part 3. Gregory Brown. O’Reilly Network.

RSpec: http://rspec.rubyforge.org/

Prototype: http://prototypejs.com/

Scriptaculous: http://script.aculo.us/

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: