joestelmach.com

Live Search With Ruby On Rails Part 4 - request.xhr?

After receiving some excellent advice from someone named Ivan, I've decided to revisit the topic of live search in Ruby on Rails yet another time. In this post written way back in February, I outlined the steps necessary to gracefully degrade the Ajax-style live search for browsers that have Javascript disabled. This required two distinct methods in the search controller: one for Javascript enabled browsers that would render the search results directly within the target element, and one for non-Javascript enabled browsers which would return the users back to the page they invoked the search from. To re-iterate, here's the search controller listing:

def search #Javascript-enabled search
  get_search_results #implementation not shown
  render :partial => "search"
end

def search_no_Javascript #Javascript-disabled search
  get_search_results #implementation not shown
  redirect_to :back
end

Admittedly, this design leaves a lot to be desired. The biggest concern here is that the code does not directly address the scenario of the user's browser having Javascript enabled, but not being able to support the XmlHttpRequest object (I say not directly since the code will still work if the user submits the form with the enter button, since no search button will be present.) The other (more theoretical) issue is that we have written two methods to do exactly the same thing, where the second method exists solely for graceful degradation of the view.

Well, it turns out that we can actually fix the latter. The framework provides us with request.xhr?, or the arguably nicer alias of request.xml_http_request?, which decides if the request has come from an Ajax-style call. The Rails API states that this decision is based on the 'X-Requested-With' header containing 'XMLHttpRequest', which is apparently done automatically by the framework whenever an Ajax request is made. This seems useful at first glance, but just remember that since this relies only on header information, it is possible that this could be simulated by any request.

OK, since I'm starting to look a bit too far into this now, let's see how this new discovery allows us to completely remove the un-needed second search method from our controller:

def search
  get_search_results
  if request.xhr?
    render :partial => "search"
  else
    redirect_to :back
end

Also, the implementation of get_search_results can be placed directly in the search method if you prefer, as the extraction of this code is no longer necessary.

This still leaves us with the problem of Javascript support without XmlHttpRequest support. Some would argue that this scenario will effect a negligible number of users, but I'd still like to figure out a way to get around this.

Comments
blog comments powered by Disqus