A Bit on Rails Partials

May 4th, 2006

Simple. To the point. Ruby on Rails partials are cool. There, I said it. Now that we are past that, let’s imagine you are coding your own blogging system of some sort. You have a blog controller with the usual suspects for actions–index, list, new, edit, update, show and destroy. Two of these actions, list and show, share a chunk of markup which represents a single blog entry. There are three ways that I currently know of to handle this.

First Way (Bad)

The first way takes me back to six months ago when I thought it was ok to repeat myself all over the place. With this approach, you markup the blog entry twice in your code like so:

list.rhtml

  1. <% for post in @posts %>
  2. <div id="post-<%= post.id %>" class="post">
  3. <h1><%= link_to post.title, :action => "show", :id => post %></h1>
  4. <div class="post-body">
  5. <%= post.body %>
  6. </div>
  7. </div>
  8. <% end %>

show.rhtml

  1. <div id="post-<%= post.id %>" class="ind-post">
  2. <h1><%= link_to post.title, :action => "show", :id => post %></h1>
  3. <div class="post-body">
  4. <%= post.body %>
  5. </div>
  6. </div>

Second Way (Better)

If you are a good little coder, you will instantly recognize that you have doubled your work and most likely slaughtered several innocent puppies so you create a partial like so:

list.rhtml

  1. <% for post in @posts %>
  2. <%= render :partial => 'post' %>
  3. <% end %>

show.rhtml

  1. <%= render :partial => 'post' %>

Third Way (Best)

Well, we have fixed our initial problem of repeating ourselves and maybe that would satisfy most. However, in the true spirit of doing everything in one line and still having it make sense (that is the Ruby way), I would one up the previous example by shrinkifying list.rhtml like so:

list.rhtml

  1. <%= render :partial => 'post', :collection => @posts %>

So what does the above line do? According to the api docs, the partial is rendered for each item in the collection. Yep, no need to loop through the collection of posts. Rails is more than happy to do it for you.

An Improvement

Often times I enjoy signifying whether the post is shown on the homepage along with several other posts or all by its lonesome. To do this, I would simply mockup my post partial like so:

_post.rhtml

  1. <div id="post-<%= post.id %>" class="<%= 'single-' if defined? single %>post">
  2. <h1><%= link_to post.title, :action => "show", :id => post %></h1>
  3. <div class="post-body">
  4. <%= post.body %>
  5. </div>
  6. </div>

The part of interest is in the first line where I check if single is defined?. If it is defined, I change the class to “single-class.” This makes it possible to style the post differently based on where it is currently being shown on your fantastical blog (homepage, archives, individually). You could also extend this to only show the excerpt on the homepage and in the archives, but the full entry when the post is all alonely. You get the idea. The end.

8 Responses to “A Bit on Rails Partials”

  1. What about using more specific selectors so that you don’t have to apply a class to the post. For example, on the single post page, you would apply a the “single” class to the body of the page (and “post” class to the post div), and then “body.single div.post” to select your post element in the CSS. And then apply a “multi” class to the body of the page with multiple posts, and then “body.multi div.post” to select the element in CSS.

    This leaves the logic out of the presentation layer.

    All that said, yours is still a good tip that could be put to good use.

  2. @Jaime - Body selectors would work perfectly fine. I would probably use id’s as opposed to a class because they will be a unique element that will only change page to page.

  3. That’s true. I just like to leave body ids for things like matching the current page to the highlighted item in the nav. Since you can only apply one ID per page, but can apply multiple classes, I thought a body class might work better in this case.

  4. Yeah, I like using the “body id=” to style the same elements differently on each page. It’s a great dry way of coding. Particularly useful for navigation and showing the user their nav selection.

    On topic: I love the use of looping through a collection in a partial. Nice write up John.

  5. [...] A Bit on Rails Partials // Archives // Addicted To New [...]

  6. Did I miss something …. where was the setp to generate or create the _”action name” partial file?

  7. avatar k-dizzle February 13th, 2008 2:40 pm

    Awesome. Thanks!

  8. avatar Curtis Duhn March 1st, 2008 1:40 am

    To make your CSS a little DRYer, you can space delimit multiple class names like <div class=”single post”>…</div> instead of <div class=”single-post”>

    Then in your CSS you can do

    # Style anything single (posts and non-posts) in a red box
    .single {
    border: solid thin red;
    }

    # Style all posts (single or collections) with a small font
    .post {
    font-size: small;
    }

    # Style single posts with a small blue font in a red box
    .single.post {
    color: blue;
    }

Leave a Reply

About This Site

Addicted to New is the personal website of John Nunemaker (Noo-neh-maker), a Web Developer enamored of Ruby on Rails and a wide-eyed fan of all things new and cool.