class BooksController < ApplicationController
def show
@book = Book.find(params[:id])
add_breadcrumb("Home", path: root_path)
add_breadcrumb("Books", path: books_path)
add_breadcrumb(@book.title)
end
end
Only the title is specific to the show method. Home should be set by the application controller and Books by the books controller code.Make this view helper.
def breadcrumb(&)
render(layout: 'common/breadcrumb', &)
end
Add this partial 'common/_breadcrumb.html.erb' (do whatever html you want): <li class="breadcrumb-item">
<%= yield %>
</li>
Add this to your layout: <% if content_for?(:breadcrumbs) %>
<ol class="breadcrumbs">
<%= yield :breadcrumbs %>
</ol>
<% else %>
Then this is how you use it in your views: <% content_for :breadcrumbs do %>
<%= breadcrumb { link_to 'Foo', foo_url } %>
<%= breadcrumb { link_to 'Bar', bar_url } %>
<%= breadcrumb { 'you are here' } %>
<% end %>
For minitest tests I add this helper: module AssertBreadcrumbs
Crumb = Struct.new(:text, :href)
# Note: the block must have 1 argument per breadcrumb. It asserts their count.
def assert_breadcrumbs(&blk)
assert_select '.breadcrumb-item', blk.parameters.size do |items|
structs = items.map { |item|
if (link = item.css('a')[0])
Crumb.new(link.text, link['href'])
else
Crumb.new(item.text.strip)
end
}
yield(*structs)
end
end
end
Which you can use in tests like this: assert_breadcrumbs do |item1, item2, item3|
assert_equal 'Foo', item1.text
assert_equal foo_url, item1.href
assert_equal 'Bar', item2.text
assert_equal bar_url, item2.href
assert_equal 'you are here', item3.text
assert_nil item3.href
end