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.
Thanks, the 'defaultcontentfor' is exactly what I was looking for. Keeping the default text in the layout really helps prevent spaghetti templates.
Joseph Pearson is a Software Inventor who graduated — somewhat improbably — with honours in History. That might seem like a bumptious little detail to record, but seriously, what else am I going to do with it?
Elegant! It keeps the default content where it naturally belongs and makes the source immediately understandable.