Rails-like content_for in Sinatra

I use content_for a lot in Rails code, but a large percentage of my projects are done as a simple Sinatra app, so I find myself missing a lot of features that Rails has. One big one was content_for – so I drafted this up to fill the void.

It is similar to how rails 2.x implements it, so in your main layout you can check if that content is there and if so display it, otherwise you can use defaults, or ignore it. This particular gist uses it to create custom sidebars based on what page you are on: if you are logged in, in a particular area, etc.. I like this approach as opposed to having a single sidebar partial with tons of display logic, I just think it keeps thing tidy.


module Sinatra::Helpers
  def section(key, *args, &block)
    @sections ||= Hash.new{ |k,v| k[v] = [] }
    if block_given?
      @sections[key] << block
      @sections[key].inject(''){ |content, block| content << block.call(*args) } if @sections.keys.include?(key)


<!-- layout.erb -->
<div id='sidebar'>
  <%= section(:sidebar) || partial(:default_sidebar) %>
# In the view
<% section(:sidebar){ partial :custom_sidebar, :local1 => blah, :local2 => blah } %>

View Gist