Saving the planet, one website at a time

Hi, I'm th3james. I build stuff with Coffeescript, Clientside MVC and Rails

Using PJAX With Rails to AJAX Navigation

PJAX is a javascript library which was mentioned by DHH in his Railsconf 11 keynote

In their own words:

pjax loads HTML from your server into the current page without a full reload. It’s ajax with real permalinks, page titles, and a working back button that fully degrades.
pjax enhances the browsing experience - nothing more.

https://github.com/defunkt/jquery-pjax

PJAX makes navigation much faster and feels more like using native app than a website. While only loading parts of the page through AJAX isn’t exactly a new thing, PJAX makes it easier to add it unobtrusively, with proper URLs and a working back button.

The project appears to be pretty new from the github page, and there isn’t a lot of documentation, so I though I’d document how I got it working with Rails 3.0

Adding PJAX to your project

First, you need to grab jquery.pjax.js and add it to your project (Oh, you’ll need JQuery too, but I’m guessing most of you have it anyway :-)

Next, add some javascript to your application.js file (or whatever your sitewide JS location is) to tell your chosen links to send using PJAX:

This code tells the browser to send all the links in ul.menu using pjax, and to load the results into the #main

This alone isn’t enough to make PJAX work. PJAX sends the request through AJAX, but if the response contains the <html>  tag, PJAX considers it a full page response, and reloads the whole page.

So, to make PJAX load the returned content into #main object, you must only return the HTML fragment, without the layout around it. To do this, you simply do a render :layout => false. However, adding this to ever controller action soon get’s pretty tedious.

Not returning a layout on PJAX requests

Thankfully, PJAX helpfully adds ’X-PJAX = true’ to its request headers. So, to return all PJAX requests without the layout file, it’s simply a case of checking for the header parameter, and adding :layout => false if so.

I did this by hacking the Rails render method:

This was the best approach I could find to do this for all requests, if anyone knows of any better ways, let me know!

That’s it!

This should be all you need to do to get PJAX working in Rails 3.0, you should find that navigation on your selected elements happens using AJAX requests in supported browsers (basically anything not IE).

You can see it in action on my band’s website:

http://barcodechannel.com