Switch_off Switch_on Switch_off
Inventive Labs: Web Problem Solvers

Providing default content in Rails layouts [04092007]

Another quick tip for Rails view developers. We commonly employ the following snippet in our layouts:

<%= (out=yield :sidebar) ? out : render(:partial => 'sidebar') %>

This thorny little one-liner says, if the view we're rendering for this layout has content_for :sidebar, show that content. Otherwise show the default content (which we've tucked away in the 'sidebar' partial).

It's a handy pattern because it lets your views opt to modify some aspect of the layout, without having to — they can go with the default sidebar content if they don't care.

However. Firstly, it's a bit unsightly. Secondly, you must put the default content in a partial (unless it's short enough to just be a string — an approach that is arguably uglier). In most cases, the default content for a block in a layout is best described in that layout, so that you don't have to go hunting down other files to get a picture of what the layout displays. Here's a better way:

<% default_content_for :sidebar do %>
  <p>This is the default sidebar content! (et cetera)</p>
<% end %>

So now, if the view specifies some content_for :sidebar, the contents of the block above (ie, the <p> tag) will not be rendered. If the view doesn't do that, then the layout will render the contents of the block.

If you'd prefer this idiom in your views, drop the following method into application_helper.rb:

def default_content_for(name, &block)
  name = name.kind_of?(Symbol) ? ":#{name}" : name
  out = eval("yield #{name}", block.binding)
  concat(out || capture(&block), block.binding)
end

This method is full of bindings and captures, which you can read up on at your leisure, or feel free to ask questions in the comments.


Andy Stewart [Tue 26 Feb 2008, 9:21pm] said:

Elegant! It keeps the default content where it naturally belongs and makes the source immediately understandable.

Joseph Wilk [Thu 3 Jul 2008, 7:18pm] said:

Thanks, the 'defaultcontentfor' is exactly what I was looking for. Keeping the default text in the layout really helps prevent spaghetti templates.

Only the comment field is required. Omitting the ID fields increases your risk of being mistaken for spam.

Preview or