Thursday, June 26, 2008

Render a collection


Very often we want to list a collection of data in front HTML page.

Let's say we have an animal collection. Each record of this collection contains animal Specie, Age, Weight and Risk. As you can imagine, the list is retrieved by

animal_controller.rb

Class AnimalController < ApplicationController
...
def show
@animals = Animal.find :all
end
...
end


Now, how shuold we render the collection?

Usually we use 'for each' against the collection to render the table:

show.html.erb

<table>
<tr><td>Specie</td>
<td>Age</td>
<td>Weight</td>
<td>Risk</td>
</tr>
<tr>
<% for each @animals do |animal| %>
<td><%= h(animal.specie) %></td>
<td><%= h(animal.age) %></td>
<td><%= h(animal.weight) %></td>
<td><%= h(animal.risk) %></td>
<% end %>
</tr>
</table>


But there is a better solution with a bonus feature, a counter of records. Once you are used to this solution, you most likely will not turn back.

The solution is to use partial with :collection function and key is NAMING CONVENTION.

The collection partial is passed in by this way:

show.html.erb

<table>
<tr><td>Specie</td>
<td>Age</td>
<td>Weight</td>
<td>Risk</td>
</tr>
<% render :partial => 'animal', :collection => @animals %>
</table>


Partial's name 'animal' will be passed into partial as a varible. It represents one record in the collection. So, 'animal' can be used to reference one record in the collection.

Here is the partial:

_animal.html.erb

<tr>
<td><%= h(animal.specie) %></td>
<td><%= h(animal.age) %></td>
<td><%= h(animal.weight) %></td>
<td><%= h(animal.risk) %></td>
</tr>


You can also add a new column to count the rows. There is a 0 based counter avaiable in partial. By naming convention, the counter variable is called animal_counter (partial-name_counter).

_animal.html.erb

<tr>
<td><%= animal_counter %></td>
...
</tr>


Don't forget using h(...) function to sanitize your passed in variable.

No comments: