Using Spacer Templates in Rails

I recently stumbled upon one of the more esoteric features of Rails when a client recently wanted to show the movement of an item through their physical locations. The request was pretty simple, we just wanted to show each “movement” in a card with a piece of UI between each set of movements.


I’ve done this in the past by looping over a collection and keeping track of the index (we don’t want an arrow at the end of our list pointing to an empty space).

<% @movements.each_with_index do |movement, index| %>
  <%= render partial: "movement", movement: movement %>
    <% unless index == (@movements.length - 1) %>
    &rarr;
  <% end %>
<% end %>

But we can do better! Rails is pretty smart about rendering collections using partials that are named conventionally.

# app/views/movements/index.html.erb
<div id="movements" class="min-w-full my-5">
  <%= render partial: @movements, spacer_template: "movement_connection" %>
</div>

# app/views/movements/_movement.html.erb
<div id="<%= dom_id movement %>" class="bg-gray-100 p-4 flex justify-between">
  <div class="space-x-2">
    <span><%= movement.origin %></span>
    <span>&rarr;</span>
    <span><%= movement.destination %></span>
  </div>

  <date><%= time_ago_in_words(movement.date) %> ago</date>
</div>

# app/views/movements/_movement_connection.html.erb
<div class="space-y-1">
  <svg viewBox="0 0 220 2" xmlns="http://www.w3.org/2000/svg">
    <rect width="2" height="2" fill="#eee" />
  </svg>
  <svg viewBox="0 0 220 2" xmlns="http://www.w3.org/2000/svg">
    <rect width="2" height="2" fill="#eee" />
  </svg>
  <svg viewBox="0 0 220 2" xmlns="http://www.w3.org/2000/svg">
    <rect width="2" height="2" fill="#eee" />
  </svg>
</div>

With the above, we can name our partials _movements.html.erb and _movement_arrow.html.erb and Rails will handle the index logic for us by only rendering our spacer template between items in the collection.

Voilà! We have a basic tracking UI. I did the SVG stuff on the fly so it currently breaks when you resize the page, but my focus was to display the helpful utility of spacer_template.

Previous
Previous

Generating ERDs for large Rails Projects

Next
Next

Generated columns in Rails 7