Simple RJS Example
Working on a contractual project on the weekend, I spent some time integrating some nifty new technology into a website. The technology was JavaScript, the crusty old web technology which has been crawling around the internet since 1995. Since it's inception JavaScript has played the central role in everything from annoying internet pop-ups to shiny WEB 2.0 sliding divs, and now they've slapped a Remote on the front of it and call it RJS.
I found a plethora of examples on the internet, but nothing that walked me from start to finish through using a RJS template in Rails. I hope that someday the following saves someone else from that void.
Take any old Rails application and add a time controller to it.
# script/generate controller time index
exists app/controllers/
exists app/helpers/
create app/views/time
exists test/functional/
create app/controllers/time_controller.rb
create test/functional/time_controller_test.rb
create app/helpers/time_helper.rb
create app/views/time/index.rhtml
The index action will be the one that Rails serves up when you head to the /time url. Modify the app/views/time/index.rhtml to look like:
<%= javascript_include_tag :defaults %>
<div id="current_time"><%= render :partial=>'time/current' %></div>
<%= link_to_remote 'refresh', :url=> {:action=>'now'} %>
Take a second to take that in, because it's the entire meat of the application. We need to include the default JavaScripts because RJS depends heavily on the Prototype library, next we created a div with the id current_time which we will use in our script magic in a second. The last line gives us a link to the now action in the time controller. We don't have that action yet, so open up app/controllers/time_controller.rb and add the new action
class TimeController < ApplicationController
def index
end
def now
end
end
The controller actions are anything but complicated, but now we need that action to return something. Usually the action looks for app/views/time/now.rhtml but execute and run app/views/time/now.rjs if it does not find it. Don't be silly and try to name your RJS templates the same as some other usable action within your application. Create app/views/time/now.rjs to read
page.replace_html 'current_time', :partial=>'time/current'
This template takes the current page, and replaces the current_time element with whatever is returned from the time/current partial. The partial is rendered from both the RJS template and the index.rhtml template is to ensure the DRYness of our logic. The app/views/time/_current.rhtml template can be as simple as
<%= Time.now().to_s %>
Now if you head to /time on your locally running WEBrick you'll see the current time, but if you mash the 'refresh' all the JavaScript magic replaces the current_time div with your partial. If you examine /time/now you'll see the RJS template is returning a script that is then run by the client's browser. You can start layering on some parameter passing and some data like XML and quickly these RJS templates become very useful in programming some crazy JavaScript, all without writing any actual JavaScript. How very Zen.





