Ruby-on-Rails
  Home arrow Ruby-on-Rails arrow Page 3 - Handling Cookies and DHTML Effects with Ru...
Dev Articles Forums 
ADO.NET  
Apache  
ASP  
ASP.NET  
C#  
C++  
ColdFusion  
COM/COM+  
Delphi-Kylix  
Design Usability  
Development Cycles  
DHTML  
Embedded Tools  
Flash  
Graphic Design  
HTML  
IIS  
Interviews  
Java  
JavaScript  
MySQL  
Oracle  
Photoshop  
PHP  
Reviews  
Ruby-on-Rails  
SQL  
SQL Server  
Style Sheets  
VB.Net  
Visual Basic  
Web Authoring  
Web Services  
Web Standards  
XML  
Mobile Linux 
App Generation ROI 
IBM® developerWorks 
Sun Developer Network 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us Get Paid 
Request Media Kit
Contact Us 
Site Map 
Privacy Policy 
Support 
 USERNAME
 
 PASSWORD
 
 
  >>> SIGN UP!  
  Lost Password? 
RUBY-ON-RAILS

Handling Cookies and DHTML Effects with Ruby on Rails
By: O'Reilly Media
  • Search For More Articles!
  • Disclaimer
  • Author Terms
  • Rating: 3 stars3 stars3 stars3 stars3 stars / 4
    2007-04-12

    Table of Contents:
  • Handling Cookies and DHTML Effects with Ruby on Rails
  • 15.13 Extracting Code into Helper Functions
  • 15.14 Refactoring the View into Partial Snippets of Views
  • 15.15 Adding DHTML Effects with script.aculo.us

  • Rate this Article: Poor Best 
      ADD THIS ARTICLE TO:
      Del.ici.ous Digg
      Blink Simpy
      Google Spurl
      Y! MyWeb Furl
    Email Me Similar Content When Posted
    Add Developer Shed Article Feed To Your Site
    Email Article To Friend
    Print Version Of Article
    PDF Version Of Article
     
     
    ADVERTISEMENT


    Handling Cookies and DHTML Effects with Ruby on Rails - 15.14 Refactoring the View into Partial Snippets of Views


    (Page 3 of 4 )

    Problem

    Your view doesn't contain a lot of Ruby code, but it's still becoming more complicated than you'd like. You'd like to refactor the view logic into separate, reusable templates.

    Solution

    You can refactor a view template into multiple templates called partials. One template can include another by calling the render method, first seen in Recipe 15.5.

    Let's start with a more complex version of the view shown in Recipe 15.5:

      <!-- app/views/list/shopping_list.rhtml
    -->
      <h2>My shopping list</h2>

      <ul>
      <% @list.each do |item| %>
       <li><%= item.name %> - 
        <%= link_to 'Delete', {:action => 'delete', :id => item.id},
                      :post => true %>
       
    </li>
      <% end %>
      </ul>

      <h2>Add a new item</h2>

      <%= form_tag :action => 'new' %>
       Item: <%= text_field "product", "name"
    %>&#x00A;
       <%= submit_tag "Add new item" %>
     
    <%= end_form_tag %>

    Here's the corresponding controller class, and a dummy ListItem class to serve as the model:

      # app/controllers/list_controller.rb
      class ListController < ActionController::Base
        def shopping_list
          @list = [ListItem.new(4, 'aspirin'), ListItem.new(199, 'succotash')]
        end

        # Other actions go here: add, delete, etc.
        # ...
      end

      class ListItem
        def initialize(id, name)
          @id, @name = id, name
        end
      end

    The view has two parts: the first part lists all the items, and the second part prints a form to add a new item. An obvious first step is to split out the new item form.

    We can do this by creating a partial view to print the new item form. To do this, create a new file within app/views/list/ called _new_item_form.rhtml. The underscore in front of the filename indicates that it is a partial view, not a full-fledged view for an action called new_item_form. Here's the partial file.

      <!-- app/views/list/_new_item_form.rhtml -->

      <%= form_tag :action => 'new' %>
      Item: <%= text_field "item", "value" %>&#x00A;
      <%= submit_tag "Add new item" %>
      <%= end_form_tag %>

    To include a partial, call the render method from within a template. Here is the _new_ item_form partial integrated into the main view. The view looks exactly the same, but the code is better organized.

      <!-- app/views/list/shopping_list.rhtml
    -->
      <h2>My shopping list</h2>

      <ul>
      <% @list.each do |item| %>
       <li><%= item.name %> -
        <%= link_to 'Delete', {:action => 'delete', :id => item.id},
                    :post => true %>
      
    </li>
      <% end %>
      </ul>
     
    <%= render :partial => 'new_item_form' %>

    Even though the filename starts with an underscore, when you call the partial, you omit the underscore.

    Discussion

    Partial views inherit all the instance variables provided by the controller, so they have access to the same instance variables as the parent view. That's why we didn't have to change any of the form code for the _new_item_form partial.

    We can create a second partial to factor out the code that prints the <LI> tag for each list item. Here's _list_item.rhtml:

      <!-- app/views/list/_list_item.rhtml -->
      <li><%= list_item.name %> -
      <%= link_to 'Delete', {:action => 'delete', :id => list_item.id},
                 
    :post => true %>
      </li>

    And heres the revised main view:

      <!-- app/views/list/shopping_list.rhtml
    -->
      <h2>My shopping list</h2>

      <ul>
      <% @list.each do |item| %>
       
    <%= render :partial => 'list_item', :locals => {:list_item => item} %>
      <% end %>
      </ul>

      <%= render :partial => 'new_item_form' %>

    Partial views do not inherit local variables from their parent view, so the item variable needs to be passed in to the partial, in a special hash called :locals. It's accessible in the partial as list_item, because that's the name it was given in the hash.

    This scenario, iterating over an Enumerable and rendering a partial for each element, is very common in web applications, so Rails provides a shortcut. We can simplify our main view even more by passing our array into render (as the :collection parameter) and having it do the iteration for us:

      <!-- app/views/list/shopping_list.rhtml
    -- >
      <h2>My shopping list</h2>

      <ul>
       
    <%= render :collection => @list, :partial => 'list_item' %>
      </ul>

      <%= render :partial => 'new_item_form' %>

    The partial is rendered once for every element in @list. Each list element is made available as the local variable list_item. In case you haven't guessed, this name comes from the name of the partial itself: render automatically gives _foo.rhtml a local variable called foo.

    list_item_counter is another variable that is set automatically (again, the name mirrors the name of the template). list_item_counter is the current item's index in the collection undergoing iteration. This variable can be handy if you want alternating list items to show up in different styles:

      <!-- app/views/list/_list_item.rhtml -- >
      <li><%= list_item.name %> -
      <% css_class = list_item_counter % 2 == 0 ? 'a' : 'b' %>
      <%= link_to 'Delete', {:action => 'delete', :id => list_item.id},
                  {'class' => css_class}, :post => true %>
      </li>

    When there's no collection present, you can pass a single object into a partial by specifying an :object argument to render. This is simpler than creating a whole hash of :locals just to pass one object. As with :collection, the object will be made available as a local variable whose name is based on the name of the partial.

    Here's an example: we'll send the shopping list into the new_item_form.rhtml partial, so that the new item form can print a more verbose message. Here's the change to shopping_list.rhtml:

      <%= render :partial => 'new_item_form', :object => @list %>

    Here's the new version of _new_item_form.rhtml:

      <!-- app/views/list/_new_item_form.rhtml -->
      <h2>Add a new item to the <%= new_item_form.size %> already in this
      list</h2>
     
    <%= form_tag :action => 'new' %>
      
    Item: <%= text_field "product", "name" %>
      
    <%= submit_tag "Add new item" %>
      <%= end_form_tag %>

    See Also

    • Recipe 15.5, "Displaying Templates with Render"

    More Ruby-on-Rails Articles
    More By O'Reilly Media


       · This article is an excerpt from the "Ruby Cookbook," published by O'Reilly. We hope...
     

    Buy this book now. This article is excerpted from chapter 15 of the Ruby Cookbook, written by Lucas Carlson and Leonard Richardson (O'Reilly, 2006; ISBN: 0596523696). Check it out today at your favorite bookstore. Buy this book now.

    RUBY-ON-RAILS ARTICLES

    - Iterating and Incrementing Strings in Ruby
    - Comparing and Manipulating Strings in Ruby
    - Strings in Ruby
    - Ruby On Rails: Making Your First Dynamic Site
    - Ruby on Rails: Beginning Rails
    - Ruby: Modules, Mixins, Fixins, and Rails
    - Controlling Information Access with the Rail...
    - URLs, Filters and the Rails Action Controller
    - Flash and the Rails Action Controller
    - Rails Action Controller
    - Dropping and Sorting with AJAX and script.ac...
    - Drag and Drop with script.aculo.us and Rails
    - Introducing script.aculo.us
    - Ruby Classes and Objects
    - Ruby Loops






    © 2003-2008 by Developer Shed. All rights reserved. DS Cluster 3 hosted by Hostway
    Stay green...Green IT