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.
I'm a Manager in R&D, currently working at
Thanks man that was helpful :)
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!