Wednesday, January 9, 2008

AJAX, Django, RoR

Michael has a couple of posts on ajax and django.  Since we occasionally discuss the merits and faults of rails and django, I thought I would provide a similar example in rails (version 2.02). At the end of this post I've included the entire source code of a rails application that creates a search form, submits the search string via XMLHttpRequest, generates random search data, updates the search results independently of the rest of the page, and for kicks - makes the search results flash.

It is simple but instructive.  To my eye, it is more elegant than the django code. for a couple of reasons:
  • No JavaScript.  I love JavaScript and have written plenty of it, but for simple and moderately complex things rails gets the abstraction correct.  Rails' ajax helpers (form_remote_tag and page in this case), do all the work for you.
  • Easy reuse of partials.   Michael had to jump through a few hoops to reuse his 'searchresults' partial (partial in rails == tag in djago). This is because django is not aware of the ajax library and thus cannot provide facilities to automate the reuse.
Edit:  My apologies for the code formatting.  The formatter I used does not recognize the html.erb syntax, and made a mess of the entire code block.

# 1) create a rails application by running "rails ajaxform" at a command prompt
# 2) create the files listed below
# 3) start the server by running "script/server" (mac,*nix) or "ruby script/server" (windows)
# 4) point your webrowser at http://localhost:3000

# ----- app/views/foos/search.html.erb -----
<% form_remote_tag(:url=>{:action=>'search'}) do %>
<%= text_field_tag('search_str') %
>
<%= submit_tag 'Search' %>
<% end %>
<%
= render :partial=>'search_results'%>

# ----- app/views/foos/_search_results.html.erb -----
<div id='search_results'
>
<%= @search_results.size > 0 ? @search_results.collect do |result| "<p>#{result}</p>" end.join : "No Search Results" %>
</div>

# ----- app/views/foos/search.js.rjs--------
page[:search_results].replace(:partial
=>'search_results')
page[:search_results].visual_effect(:pulsate) # just for fun!`

# ----- app/controllers/foos_controller.rb -----
class FoosController < ApplicationController
def search
@search_results=[]
if search_str=params[:search_str]
@search_results = (1..rand(10)).collect do |ii| "#{search_str} + #{ii}" end
end
respond_to do |format|
format.html
format.js
end
end
end

# ----- app/views/layouts/application.html.erb -----
<html>
<head>
<%=javascript_include_tag :defaults%>
</head>
<body>
<%
= yield %>
</body
>
</html>