Tip: Boring breadcrumbs for Rails
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.
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.