Close and Go BackBack to Viget

Getting Started With RJS in Rails

Patrick Reagan
Patrick Reagan, Development Director, November 22, 2006 0 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.

Trackback URL: Trackbacks are disabled for this entry

Comments for this entry were closed after 60 days.

A Development Community for Viget Labs and Beyond

Every team member here at Viget Labs strives to be an innovator. We members of the development team are no different - that's why we're constantly engaging in community discussions and exploring the unknown that is the next generation of open-source web applications.

Viget Is Hiring!

Viget has job openings for Ruby Developers, Interns, and Front-End Developers. Learn More »

Recent Comments

I think that polymorphic_url(@commentable, :anchor => “comment_#{@comment.id}") should work. You can also refactor the “comment_#{@comment.id}” to a separated method, like dom_id, which returns the dom identifier of the comment.