-
Fighting with Ajax
I just had a very frustrating day fighting with Ajax. I thought I’d document some of these things.Does your GET or POST hit the server but you see no response data come back?
I saw this because I was debugging this in a separate file (using Open File in my browser), outside my (Rails) project. WTF I thought
Turns out that even though I thought it hit the server, it was returning no data because of the cross-site scripting policy.
Solution? Learn JSONP
JSONP: what does that jQuery even look like?
I finally got this right:
$.ajax({url: "http://localhost:3000/api/test.js", dataType: "jsonp", success: function(data) { $("#ajax_success").html("Success!"); }, });Solution: Important parts here that I found: dataType: “jsonp” and the URL ending in a “.js”
Also note that the success function is what’s called, even with a JSONP request, when the AJAX call returns. Yes, it’s the same interface from a JSON call, and that’s cool.
(You can override this, but the success callback is a clean API. I like it)
RAILS, Y U NO FIND GET ROUTE FOR MY REQUEST?
JSONP only works via GET, because it works through the same mechanism that you would get an image from a web server - just a link. So, with that in mind, your actions need to respond to GETs too.
I had a line in my routes.rb file like
resource :test, :only => [:create]To make that respond to both a GET and POST I had to do this ugly thing:resource :test, :only => [:create] do get :create post :create endSolution: use this method. No, I couldn’t get
:via =>, to workOk, what does my action have to return?
So the JSONP support in Rails (3) is there, but it’s somewhat manual. I want to be able to return both JSON and JSONP, and I want to return my result in both cases.
My current solution is ugly as sin
json = { :success => true }.to_json respond_to do |format| format.json { render :json => json } format.js { render :json => json, :callback => params[:callback] } endPotential gotcha: in the format.js block, make sure the
:callbackkey is outside the hash you want to return. This is hard to miss, and one of the reasons I made the hash as a separate object (the other is to try to make it DRYer)If you see that your JSON response is coming out:
{"success": true, "callback": "...."}you’d made the mistake above.Solution: Use this pattern, and hope for a better future
I do have hope on Rack middleware, but I couldn’t figure out how to use the two rack middleware packages I found (Rack/Contrib nor Rack JSONP Middleware. I’m working with the latter author to get his solution into my app, because seriously? I want it DRY
Comments?
Seriously, if you have a suggestion for things I listed here, I’m all ears
-
digitalwestie reblogged this from rwilcox
-
digitalwestie liked this
-
rwilcox posted this
-