Counters in partials, a little-known rails feature!

I don’t normally post rails tips that are New To Me, because I always feel like I’m late to the party and everyone knows the tip already. This one however, I vetted through some very experienced rails developers and it was new to them as well. Which is strange, because looking back, I think it was first added in 2004!

The feature I’m talking about is counters in partials used in a collection. Let me show you:

<%= render :partial => “book”, :collection => @books %>

As you know, that will loop through the array of @books and use the template _book.html.erb (by default) each time. Let’s take a look at that file and see how we can use the counter:

<div>
  Number: <%= book_counter %><br/>
  Title: <%= h book.title %><br/>
  Author: <%= h book.author %><br/>
</div>

That will give us output like this:

<div>
  Number: 0<br/>
  Title: Promises in Death<br/>
  Author: J. D. Robb<br/>
</div>

<div>
  Number: 1<br/>
  Title: One Day at a Time<br/>
  Author: Danielle Steel<br/>
</div>

<div>
  Number: 2<br/>
  Title: First Family<br/>
  Author: David Baldacci<br/>
</div>

What’s this useful for?
I can think of two things off the top of my head:

  • Zebra Tables
  • Special classes for first or last elements to change them visually

Let me know here or on twitter (@kastner) if this was helpful (or any other little-known tips)

9 thoughts on “Counters in partials, a little-known rails feature!”

  1. @Dieter I also use and prefer the cycle for zebra tables.

    @Erik thanks! I don’t think I have used this, although I think I *once* saw it in a doc once and then promptly forgot it.

    I am thinking that the case for “special classes for first or last elements to change them visually” is only really useful for “first element” scenario not “last element” or am I missing something? Without passing in more locals to the partial how would you know how many was in the collection?

    Let me know if I am missing something.

    Thanks appreciate the tidbit!

  2. You’d have to figure out it’s the last one somehow. One way (although it’s kind of “dirty”) is to just use the collection your iterating over, like this: @books.size == book_counter.

    A cleaner would be to pass the size of the collection in a :local

  3. For the last element it’s quite simple
    just compare your current element with the last of the collection.

    For example:

    if @races.last == race

    Unless your collection is a local variable of the previous view, but I guess it’s not the case.

  4. Damien, you can totally do that, but to me it violates separation of concerns – a partial called for a collection shouldn’t know anything about the collection.

  5. Very nice. Funny, I was actually looking up “rails counter” in google to find your blog posting, but ironically I actually DID need it for a “zebra table”. Perfect! Thanks.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>