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.
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.