Background:
I use “rails g scaffold hotel name stars:integer” to start fast (and insert into the database some records),
and write a Backbone client outside the rails app.
I open the Backbone client locally with Safari file:///Users/lg/Workspace/www/index.html for testing the client because my idea is to put the rails server on a host (ex. Heroku) and insert the Backbone client into a PhoneGap App.
My backbone client is only few lines:
Hotel = Backbone.Model.extend({
initialize: function(){
console.log("initialize Hotel")
}
});
Hotels = Backbone.Collection.extend({
model: Hotel,
url: 'http://0.0.0.0:3000/hotels'
});
But when i fetch hotels with backbone, rails responds with the format.html and not the format.json which Backbone can parse.
hotels_controller.rb
# GET /hotels
# GET /hotels.json
def index
@hotels = Hotel.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: @hotels }
end
end
Safari inspector console:
hotels = new Hotels()
Object
hotels.fetch()
Object
hotels.length
0
Request URL:http://0.0.0.0:3000/hotels
Request method:GET
Status code:200 OK
Request Headers
Accept:application/json, text/javascript, */*; q=0.01
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/534.53.11 (KHTML, like Gecko) Version/5.1.3 Safari/534.53.10
Response Headers
Cache-Control:max-age=0, private, must-revalidate
Connection:Keep-Alive
Content-Length:2233
Content-Type:text/html; charset=utf-8
Date:Sat, 11 Feb 2012 14:31:52 GMT
Etag:"606da2b7c21ca96c9d71aabccdd439e9"
Server:WEBrick/1.3.1 (Ruby/1.9.2/2011-07-09)
EDIT:
Updated with url set to url: “http://0.0.0.0:3000/hotels.json
it can fatch but can’t make others CRUD (example PUT)
hotels = new Hotels()
Object
hotels.fetch()
Object
hotels.length
5
hotel = hotels.get(2)
Object
hotel.set({name: "name 2"})
Object
hotel.save()
Object
PUT http://0.0.0.0:3000/hotels.json/2 404 (Not Found)
Instead if i set only /hotels it works (but the backbone client must reside on the server)
EDIT 2:
uploaded the code on github
https://github.com/RevH/backbonefails
EDIT 3:
Another details is if you insert the backboneclient directory into Rails public directory and change 0.0.0.0:3000/hotels.json to /hotels it works fantastic!! But if i separate the client from server and open it with Safari it require .json at the end of the url. this is very strange.
i open a rails issue on github at https://github.com/rails/rails/issues/5005
The important thing to understand is that best practice in Rails is NOT to use the Accept headers. There is a nice writeup here that explains why in glorious detail. Summary is browser implementation of HTTP Accept headers is broken. Rails best practice is to set the :format parameter in the request. However, if you like the accept headers they are supported but the rules around what is a valid accept header in rails can be tricky. If your accept header matches the following regex:
then rails throws it away and defaults to text/html mime type. I know, right? Your header happens to match this. The reason most people don’t have this problem is that rails “fixes” the default jquery behavior in the rails jquery-ujs. They set a ajaxSetup beforeSend callback in JQuery that puts the
*/*at the beginning of the header, which is what the magic rails regex wants to see though I can’t really tell why, other than they know that an unmodified browser request will always put it there. Here is how you might fix your accept header in JQuery.