Using a partial as an optional layout

Posted on December 25, 2011

Rails uses partials a lot, and you can even use partials as mini-layouts. What I wanted to do is render flashes either as a normal partial (i.e. passing a string of text to be displayed), or as a layout (passing a block of markup to be rendered).

The idea

I’m using Twitter’s Bootstrap CSS message-box to style my flashes, and I wanted to extract the common functionality to be able to call (e.g.) an error message box like this using a block to be rendered:

  
  
    
    = render layout: "common/alerts/alert_message_box", locals: { type: :error } do
      = error_messages_for @customer
  
    
  

But I also wanted the option to pass basic text and have it displayed within the message-box, like so

  
  
    
    = render "common/alerts/alert_message_box", content: "You've got errors"
  
    
  

Extracting Bootstrap message-boxes

I simply created a partial with this code:

  
  
    - options ||= {}
- options[:class] = Array(options[:class]) << "alert-message block-message fade in #{type}"
- options[:class] = options[:class].join(' ')
%div{ options.merge({'data-alert' => 'alert'}) }
= link_to 'x', '#', :class => 'close'
- if defined?(content)
  = content
- else
  = yield
  
  

Besides the markup needed for the message-box functionality (adding a close link, setting a ‘data-alert’ HTML attribute, etc.), you can see that I simply check if a `content` value was passed to the partial. If that’s the case, we simply want to display that. Otherwise, we yield to the block that has been passed and the block’s content will be rendered within the message-box.

Pretty straightforward, but cuts down a lot on non-DRY code…


Would you like to see more Elixir content like this? Sign up to my mailing list so I can gauge how much interest there is in this type of content.