Getting Started With RJS in Rails

One of the features of Rails that makes it a great framework for building the next generation of "Web 2.0" applications is its tight integration with the script.aculo.us JavaScript library. What this means for your application is the ability to dynamically update the display based on the results of an action (in this case '/task/mark_complete'):
 def mark_complete begin @task = Task.find(params[:id]) @task.task_status_id = TaskStatus::COMPLETE @task.save rescue ActiveRecord::RecordNotFound render :nothing => true return end render_text @task.status.description end 

Adding this code in a view template is all we need to have our display automatically update:

 

Status: <%= @task.status.description %>

<%= link_to_remote 'Mark as Complete', :update =>, 'task-status-' + @task.id.to_s, :url => {:controller => 'task', :action => 'mark_complete', :id => @task %>

This works great for those times when we only need to update a single DOM element on a page. What about when we need to update multiple pieces of content on the same page? One solution that has worked quite well for us is the use of RJS templates in Rails.To take our simple example a bit further, let's say that when we mark a task as complete, we want to update some general task list reporting information and highlight the current task after the update occurs. Here is our status information and task listing in the view:
 Completed: <%= Task.completed_count %> task(s)
Remaining: <%= Task.remaining_count %> task(s) <% for task in @tasks %>
Task: <%= h task.title %>
Status: <%= task.status.description %>
<%= link_to_remote 'Mark as Complete', :url => {:controller => 'task', :action => 'mark_complete', :id => task} %> <% end %>
This is where the RJS template comes into play – we'll write the Ruby code to update the display and then wire it into our action. This content will go in 'views/task/_update_tasks.rjs':
 page.replace_html('tasks-completed', Task.completed_count) page.replace_html('tasks-remaining', Task.remaining_count) page.replace_html('task-status-' + @task.id.to_s, @task.status.description) page.visual_effect(:highlight, 'task-item-' + @task.id.to_s, :duration => 1.0) 
Now, we'll go back to the action and wire it up to use our new RJS template. The 'render_text' line is all that's changed from the original example – I'll include the full sample for clarity:
 def mark_complete begin @task = Task.find(params[:id]) @task.task_status_id = TaskStatus::COMPLETE @task.save rescue ActiveRecord::RecordNotFound render :nothing => true return end render :partial => 'update_tasks' end 
That's all there is to it, now when you flag a task as completed you'll get the feedback immediately in your browser.

Patrick is development director in Viget's Boulder, CO, office. He writes clean Ruby code and automates system infrastructure for clients such as Shure and Volunteers of America.

More posts by Patrick