Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails Odd Even If Statement

I have a loop for my Activity model

<% @activities.each do |activity| %>
<div>
    <div class="cell">
        <%= image_tag(activity.image) %>
    </div>
    <div class="cell">
        <h4><%= activity.title %></h4>
        <p><%= activity.description %></p>
        <span><%= activity.distance %></span>
    </div>
</div>
<% end %>  

I want to create a zig-zag effect, so I need to re-arrange the HTML for every even activity, so the markup will look like this:

<div>
  <div class="cell">
    <h4><%= activity.title %></h4>
    <p><%= activity.description %></p>
    <span><%= activity.distance %></span>
  </div>
  <div class="cell">
    <%= image_tag(activity.image) %>
  </div>
</div>

Is there a way to do this with an if statement? Something like this:

<% if activity.odd? %>
 <% @activities.each do |activity| %>
   <div>
     <div class="cell">
   <%= image_tag(activity.image) %>
 </div>
 <div class="cell">
   <h4><%= activity.title %></h4>
   <p><%= activity.description %></p>
   <span><%= activity.distance %></span>
 </div>
   </div>
  <% end %>
<% else %>
  <% @activities.each do |activity| %>
    <div>
      <div class="cell">
    <h4><%= activity.title %></h4>
    <p><%= activity.description %></p>
    <span><%= activity.distance %></span>
  </div>
  <div class="cell">
    <%= image_tag(activity.image) %>
      </div>
</div>
<% end %>
like image 326
colmtuite Avatar asked Aug 25 '12 14:08

colmtuite


1 Answers

There are a few ways to do this.

  1. The first and best way is to do this with CSS's nth-child selector, assuming it's possible to achieve your desired effect purely through CSS. Use nth-child(odd) or nth-child(even), as described in Alternate table row color using CSS?

  2. If you're iterating over a collection using .each, you can add a .with_index and check whether the index is odd or even:

    <% @activities.each.with_index do |activity, index| %>
      <% if index.odd? %>
        ...
      <% else %>
        ...
      <% end %>
    <% end %>
    

    Note that by default the index is zero-based, so your first element will be considered "even". You can pass a starting index of 1 to with_index if you want the alternating to start odd instead:

    <% @activities.each.with_index(1) do |activity, index| %>
    
  3. An alternative to using with_index is to use Rails' cycle helper, which "magically" returns the next argument in rotation each time its invoked:

    <% @activities.each do |activity| %>
      <% if cycle('odd', 'even') == 'odd' %>
        ...
      <% end %>
    <% end %>
    

Also note that this is a fantastic opportunity for refactoring. You should distill the two reused cell divs into their own partials and render them in the order you want:

<% if index.odd? %>
  <%= render h4_part %>
  <%= render img_part %>
<% else %>
  <% render img_part %>
  <% render h4_part %>
<% end %>
like image 87
meagar Avatar answered Nov 14 '22 14:11

meagar