<% i = 0 %>
<% @patients.each do |patient| %>
<tr class="<%= i % 2 == 0 ? 'Even' : 'Odd' %>">
<td><%= link_to patient.id, patient %></td>
<td><%= patient.user.username %></td>
<td><%= patient.user.first_name %></td>
<td><%= patient.user.last_name %></td>
<td><%= patient.user.email %></td>
<td><%= patient.user.active %></td>
<td><%= patient.user.disabled %></td>
<td>
<ul class="Horizlist">
<li><%= link_to 'Detail', patient %></li>
</ul>
</td>
</tr>
<% i += 1 %>
I don't like that I have to define an i variable, is there a better way?
2 Answers 2
Rails has a built in method, cycle
, which will cycle between two more more options for you, so you don't have to manage the "Even"/"Odd" selection.
<% @patients.each do |patient| %>
<%= content_tag :tr, :class => cycle('Even', 'Odd') do %>
<%= content_tag :td, link_to(patient.id, patient) %>
<% [:username, :first_name, :last_name, :email, :active, :disabled].each do |property| %>
<%= content_tag :td, patient.user.send(property) %>
<% end %>
<td>
<ul class="Horizlist">
<%= content_tag :li, link_to('Detail', patient) %>
</ul>
</td>
<% end %>
<% end %>
If you happen to use Haml, it looks quite nice. :)
- @patients.each do |patient|
%tr{:class => cycle('Even', 'Odd')}
%td= link_to(patient.id, patient)
- [:username, :first_name, :last_name, :email, :active, :disabled].each do |property|
%td= patient.user.send(property)
%td
%ul.Horizlist
%li= link_to('Detail', patient)
-
\$\begingroup\$ Damn, how did I not know that? This is of course better than defining your own helper. +1 \$\endgroup\$sepp2k– sepp2k2011年02月25日 10:08:33 +00:00Commented Feb 25, 2011 at 10:08
-
\$\begingroup\$ Also, if this is just for styling purposes: you can do that with CSS without
class
es. \$\endgroup\$user36– user362012年01月31日 19:43:39 +00:00Commented Jan 31, 2012 at 19:43
First of all ruby has an each_with_index
method, so you can do @patients.each_with_index do |patient, i|
instead of keeping a counter manually.
However with the conditional inside the loop that is still too much logic for the view in my opinion. What I'd do is define a helper for this, which might look like this:
# For each item in the given collection, yield that item and embed the
# result in the given tag. The class attribute of that tag alternates
# between class1 and class2
def alternating(collection, tag, class1, class2, html => {})
collection.each_with_index do |item, i|
html[:class] = i % 2 == 0 ? class1 : class2
content_tag(tag, html, false) do
yield item
end
end
end
And then call it like this:
<% alternating(@patients, :tr, 'Even', 'Odd') do |patient| %>
<td><%= link_to patient.id, patient %></td>
<td><%= patient.user.username %></td>
<td><%= patient.user.first_name %></td>
<td><%= patient.user.last_name %></td>
<td><%= patient.user.email %></td>
<td><%= patient.user.active %></td>
<td><%= patient.user.disabled %></td>
<td>
<ul class="Horizlist">
<li><%= link_to 'Detail', patient %></li>
</ul>
</td>
<% end %>