Boring Rails

Tip: Boring breadcrumbs for Rails

:fire: Tiny Tips

Breadcrumbs are a common UI pattern in most software applications. Rails has no built-in tools specifically for breadcrumbs, and while there are a handful of existing gems, I think this is something you can easily implement in your own app with just a few lines of code.

Ultimately, you’ll want control of how you display the breadcrumbs in your app so you might as well just own all the code for this functionality.

Usage

First, add a model for a Breadcrumb. This can live in the app/models folder but does not need to be an ActiveRecord model since we don’t need it to persist to the database.

class Breadcrumb
  attr_reader :name, :path

  def initialize(name, path)
    @name = name
    @path = path
  end

  def link?
    @path.present?
  end
end

Next add a method to your ApplicationController to store and add breadcrumbs.

class ApplicationController < ActionController::Base
  ...

  helper_method :breadcrumbs

  def breadcrumbs
    @breadcrumbs ||= []
  end

  def add_breadcrumb(name, path = nil)
    breadcrumbs << Breadcrumb.new(name, path)
  end
end

Then in your layout, you can render the breadcrumbs however you’d like. In my applications, I use the breadcrumbs in both the <title> head tag and in the page header.

<head>
  <title>
    <%= breadcrumbs.map(&:name).reverse.append("My App").join(" | ") %>
  </title>
</head>

<nav>
  <ol class="breadcrumbs">
    <% breadcrumbs.each do |crumb| %>
     <li>
      <% if crumb.link? %>
        <%= link_to crumb.name, crumb.path, class: "breadcrumb-link" %>
      <% else %>
        <span class="breadcrumb-page">
          <%= crumb.name %>
        </span>
      <% end %>

      <% unless crumb == breadcrumbs.last %>
        <span class="breadcrumb-separator">/</span>
      <% end %>
     </li>
    <% end %>
  </ol>
</nav>

It’s a simple API, but this model will allow you to add breadcrumbs in each of your controllers. The breadcrumb can include an optional path if you want it to be a link.

You can setup breadcrumbs in before_actions or inside each action. You can add conditional logic just like with any regular Ruby code.

class PostsController < ApplicationController
  before_action :set_breadcrumbs

  def index
    @posts = Post.all
  end

  def show
    @post = Post.find(params[:id])

    add_breadcrumb(@post.title, @post)
  end

  def new
    @post = Post.new

    add_breadcrumb("New Post")
  end

  private

  def set_breadcrumbs
    add_breadcrumb("Admin", admin_home_path) if Current.user.admin?
    add_breadcrumb("Posts", posts_path)
  end
end

Sexy? No. Boring? Yes. Works great? Of course.

If you like these tips, you'll love my Twitter account. All killer, no filler.