RESTful API with JSON messages in Rails 3 and jQuery

Rails 3 makes it really easy to return JSON data in the HTTP response. Consider this fragment:

class ListsController < ApplicationController
 
  respond_to :json
 
  def index
    @lists = List.all
    respond_with(@lists)
  end
 
  # ...
end

index might return e.g.

If you look at jQuery-ujs when sending an Ajax request, the content type is set to ‘application/x-www-form-urlencoded’ by default: The data is serialized as form data and send through the wire.

While this is absolutely fine, I was wondering how to use ‘application/json’ as content type when sending an Ajax request with jQuery. IMHO that’s cleaner because you then send JSON in the request and get back JSON in the response. Content types like ‘application/json’ and ‘text/xml’ are also much better if 3rd party applications will consume your service.

Rails by default creates seven different routes for a single (not nested) resource:

          GET    /lists(.:format)               {:action=>"index", :controller=>"lists"}
    lists POST   /lists(.:format)               {:action=>"create", :controller=>"lists"}
 new_list GET    /lists/new(.:format)           {:action=>"new", :controller=>"lists"}
          GET    /lists/:id(.:format)           {:action=>"show", :controller=>"lists"}
          PUT    /lists/:id(.:format)           {:action=>"update", :controller=>"lists"}
     list DELETE /lists/:id(.:format)           {:action=>"destroy", :controller=>"lists"}
edit_list GET    /lists/:id/edit(.:format)      {:action=>"edit", :controller=>"lists"}

Below the jQuery Ajax code for each of these routes:

GET /lists(.:format) {:action=>"index", :controller=>"lists"}

$.ajax({
	url: "http://localhost:3000/lists",
	dataType: "json",
	type: "GET",
	processData: false,
	contentType: "application/json"
});

POST /lists(.:format) {:action=>"create", :controller=>"lists"}

$.ajax({
	url: "http://localhost:3000/lists",
	dataType: "json",
	type: "POST",
	processData: false,
	contentType: "application/json",
	data: "{\"list\":{\"title\":\"test\"}}"
});

GET /lists/new(.:format) {:action=>"new", :controller=>"lists"}

// .new
$.ajax({
	url: "http://localhost:3000/lists/new",
	dataType: "json",
	type: "GET",
	processData: false,
	contentType: "application/json"
});

GET /lists/:id(.:format) {:action=>"show", :controller=>"lists"}

$.ajax({
	url: "http://localhost:3000/lists/3",
	dataType: "json",
	type: "GET",
	processData: false,
	contentType: "application/json"
});

PUT /lists/:id(.:format) {:action=>"update", :controller=>"lists"}

$.ajax({
	url: "http://localhost:3000/lists/3",
	dataType: "json",
	type: "POST",
	processData: false,
	contentType: "application/json",
	data: "{\"list\":{\"title\":\"hallo welt\"}}",
	beforeSend: function(xhr)   
	{
		xhr.setRequestHeader("X-Http-Method-Override", "PUT");
	}
});

DELETE /lists/:id(.:format) {:action=>"destroy", :controller=>"lists"}

$.ajax({
	url: "http://localhost:3000/lists/3",
	dataType: "json",
	type: "POST",
	processData: false,
	contentType: "application/json",
	beforeSend: function(xhr)   
	{
		xhr.setRequestHeader("X-Http-Method-Override", "DELETE");
	}
});

GET /lists/:id/edit(.:format) {:action=>"edit", :controller=>"lists"}

// .edit
$.ajax({
	url: "http://localhost:3000/lists/3/edit",
	dataType: "json",
	type: "GET",
	processData: false,
	contentType: "application/json"
});

Note that you need to override the HTTP method for update and destroy. You could use also type: “PUT” and type: “DELETE”, but not all browsers understand these verbs. Therefore it’s probably better to use the ‘X-Http-Method-Override’ header instead.

For those routes which require to send data, the data is send as JSON. The format of the JSON string needs to match what Rails would return in the response. If you used a different JSON string, you would have to parse it server side by yourself.

processData is set to false. If it is ‘true’ (the default), jQuery will try to serialize it into a form post. In this case that’s not desirable, that’s why it needs to be turned off.

DeliciousTwitterFacebookLinkedInRedditSlashdotTechnorati FavoritesDiggShare
This entry was posted in jQuery, RubyOnRails. Bookmark the permalink.

2 Responses to RESTful API with JSON messages in Rails 3 and jQuery

  1. Todor Grudev says:


    Thanks man that was helpful :)

  2. Raju says:


    Interesting, I’ll give it a try. It was IE7 s refusal to usmbit my call to getJSON that initially brought me here. I’ve done more testing and determined that it always works as long as:1. The data’ argument isn’t too long. Somewhere around 2048 is the limit for IE get requests, including the base URL.2. I call $.ajaxSetup({ cache: false }); before I send the getJSON request.All well and good unless you have a lot of data to send, which I do. So I’m going to give your approach a try, thanks!

Leave a Reply

Your email address will not be published. Required fields are marked *

*


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>