Pretty Page Title in Rails 3

2010-05-17 20:00:00 -0400

Ryan Bates has an incredible video tutorial series called Railscasts. They’re really fantastic, and the recent ones focusing on Rails 3 development are invaluable to someone like me who’s playing catch-up, having been in iPhone SDK land for what seems like the last six months.

In any event, he posted this nice trick a while back, called Pretty Page Title. You can watch the railscast for all the details, but the basics of it are a means to set a default bit of content in your layout, and override it from a particular page view. The most obvious example is the HTML title element, but we also need it for things like page description, keywords, other meta content. Here’s what the code looks like:

# application_helper.rb
def title(page_title)
content_for(:title) { page_title }

<!-- layouts/application.rhtml -->
<title>Shoppery - <%= yield(:title) || "The Place to Buy Stuff" %></title>

The crux of the trick is the || operator. If yield returns some value evaluating to false (such as nil), “The Place to Buy Stuff” becomes the content. This is important because it means in a particular view page file, you could over-ride this. Pretty handy for product pages or individual blog posts!

<!-- show.html.haml -->
- page_title(@article.title)
= render @article

This trick no longer works, because content_for returns a blank string when no content has been supplied. I’m not sure when it stopped returning nil, but that’s the case, and I suspect it’s a Rails 3 thing.

In the spirit of giving back (and because I needed it), I hacked up an alternative that’s working pretty nicely for us on a new project (replacing our blog in Radiant with a custom Rails 3 blog). The idea is to check content_for for any content in a helper method and return default content if it’s blank. Here it is as a Github gist, hopefully this loads nicely:

This works because content_for acts as a kind of accessor (both get and set) for the content you pass to it. No need for yield! Which is good, because if you try to call yield inside the helper method, you’ll be treated to the actual Ruby yield, which won’t look kindly on your symbol ;-)

blog comments powered by Disqus