How-To Make a Rails Partial With Optional Locals (Parameters)

Berkeley, CA: Aug 25, 2007
by Matthew Moore

Just a quick post today! In an effort to help our ThriveSmart code stay DRY, I have been treating my partials a lot like methods that can output varying HTML based on the parameters passed in. Let me give an example:

<% # Parameters: upload_path, unique_name,
   #         title = nil, other = nil %>

This outputs the <%= upload_path %>

<% if title then %>
  Output the title <%= title %> only if there was one.
<% end %>

The problem with this is that every time you call the partial, you have to send in nils for the optional locals regardless (e.g. :title => nil, :other => nil) with your render call, as shown below

<%= render :partial => 'shared/my_partial',
    :locals => {
        :upload_path => 'dumdeedum',
        :unique_name => "slideshow",
        :title => nil, 
        :other => nil 
    } %>

Knowing this wasn't particularly elegant, I wanted a better solution. Here's how you make the title and other local variable optional.

UPDATE: for a reason I still don't understand, unless defined?(x) doesn't always perform as you'd expect in a partial. I've switched to using local_assigns[:x].nil? (.nil? to get around if x == false). This solution currently doesn't seem work with HAML, but works like a charm in RHTML.

<%
  # Parameters: upload_path, unique_name, title = nil, other = nil
  # title = nil unless defined?(title) -- doesn't work
  # other = nil unless defined?(other) -- doesn't work

  title = nil if local_assigns[:title].nil? 
  other = nil if local_assigns[:other].nil? 
%>

This outputs the <%= upload_path %>

<% if title then %>
  Output the title <%= title %> only if there was one.
<% end %>

Now you can call it and leave off the optional parameters as you please!

<%= render :partial => 'shared/my_partial',
    :locals => {
        :upload_path => 'dumdeedum',
        :unique_name => "slideshow"
    } %>

Well, I hope this make your code DRY as it's helped make ours!