Simple RJS Example

Wasabi Pisum Sativum

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.

1 Comment »

  1. possum Said,

    March 18, 2010 @ 12:18 am

    This cleared up a lot of little things on which I was tripping up. Thanks for a clear, step by step process that worked for me!

RSS feed for comments on this post · TrackBack URI

Leave a Comment