(TL;DR) Gretel is a Ruby on Rails plugin that makes it easy yet flexible to create breadcrumbs. It is based around the idea that breadcrumbs are a concern of the view, so you define a set of breadcrumbs in config/breadcrumbs.rb (or multiple files; see below) and specify in the view which breadcrumb to use. Gretel also supports semantic breadcrumbs (those used in Google results).
Have fun!
In your Gemfile:
gem "gretel"
And run:
$ bundle install
Start by generating breadcrumbs configuration file:
$ rails generate gretel:install
Then, in config/breadcrumbs.rb:
# Root crumb
crumb :root do
link "Home", root_path
end
# Issue list
crumb :issues do
link "All issues", issues_path
end
# Issue
crumb :issue do |issue|
link issue.title, issue
parent :issues
end
At the top of app/views/issues/show.html.erb, set the current breadcrumb (assuming you have loaded @issue
with an issue):
<% breadcrumb :issue, @issue %>
Then, in app/views/layouts/application.html.erb:
<%= breadcrumbs pretext: "You are here: ",
separator: " › " %>
This will generate the following HTML (indented for readability):
<div class="breadcrumbs">
<span class="pretext">You are here:</span>
<a href="/">Home</a> ›
<a href="/issues">All issues</a> ›
<span class="current">My Issue</span>
</div>
You can pass options to <%= breadcrumbs %>
, e.g. <%= breadcrumbs pretext: "You are here: " %>
:
Option | Description | Default |
---|---|---|
:style | How to render the breadcrumbs. Can be :inline , :ol , :ul , or :bootstrap . See below for more info. |
:inline |
:pretext | Text to be rendered before breadcrumb, e.g. "You are here: " . |
None |
:posttext | Text to be appended after breadcrumb, e.g. "Text after breacrumb" , |
None |
:separator | Separator between links, e.g. " › " . |
" › " |
:autoroot | Whether it should automatically link to the :root crumb if no parent is given. |
True |
:display_single_fragment | Whether it should display the breadcrumb if it includes only one link. | False |
:link_current | Whether the current crumb should be linked to. | False |
:link_current_to_request_path | Whether the current crumb should always link to the current request path. Note: This option will have no effect unless :link_current is set to true . |
True |
:semantic | Whether it should generate semantic breadcrumbs. | False |
:id | ID for the breadcrumbs container. | None |
:class | CSS class for the breadcrumbs container. Can be set to nil for no class. |
"breadcrumbs" |
:fragment_class | CSS class for the fragment link or span. Can be set to nil for no class. |
None |
:current_class | CSS class for the current link or span. Can be set to nil for no class. |
"current" |
:pretext_class | CSS class for the pretext, if given. Can be set to nil for no class. |
"pretext" |
:posttext_class | CSS class for the posttext, if given. Can be set to nil for no class. |
"posttext" |
:link_class | CSS class for the link, if given. Can be set to nil for no class. |
None |
:container_tag | Tag type that contains the breadcrumbs. | :div |
:fragment_tag | Tag type to contain each breadcrumb fragment/link. | None |
:aria_current | Value of aria-current attribute. |
None |
:link_data | Adds data attributes to breadcrumb | nil |
These are the styles you can use with breadcrumbs style: :xx
.
Style | Description |
---|---|
:inline |
Default. Renders each link by itself with › as the seperator. |
:ol |
Renders the links in <li> elements contained in an outer <ol> . |
:ul |
Renders the links in <li> elements contained in an outer <ul> . |
:bootstrap |
Renders the links for use in Bootstrap v3. |
:bootstrap4 |
Renders the links for use in Bootstrap v4. |
:bootstrap5 |
Renders the links for use in Bootstrap v5. |
:foundation5 |
Renders the links for use in Foundation 5. |
Or you can build the breadcrumbs manually for full customization; see below.
If you add other widely used styles, please submit a Pull Request so others can use them too.
In config/breadcrumbs.rb:
# Root crumb
crumb :root do
link "Home", root_path
end
# Regular crumb
crumb :projects do
link "Projects", projects_path
end
# Parent crumbs
crumb :project_issues do |project|
link "Issues", project_issues_path(project)
parent project # inferred to :project
end
# Child
crumb :issue do |issue|
link issue.name, issue_path(issue)
parent :project_issues, issue.project
end
# Recursive parent categories
crumb :category do |category|
link category.name, category
if category.parent
parent category.parent # inferred to :category
else
parent :categories
end
end
# Product crumb with recursive parent categories (as defined above)
crumb :product do |product|
link product.name, product
parent product.category # inferred to :category
end
# Crumb with multiple links
crumb :test do
link "One", one_path
link "Two", two_path
parent :about
end
# Example of using params to alter the parent, e.g. to
# match the user's actual navigation path
# URL: /products/123?q=my+search
crumb :search do |keyword|
link "Search for #{keyword}", search_path(q: keyword)
end
crumb :product do |product|
if keyword = params[:q].presence
parent :search, keyword
else # default
parent product.category # inferred to :category
end
end
# Multiple arguments
crumb :multiple_test do |a, b, c|
link "Test #{a}, #{b}, #{c}", test_path
parent :other_test, 3, 4, 5
end
# Breadcrumb without link URL; will not generate a link
crumb :without_link do
link "Breadcrumb without link"
end
# Breadcrumb using view helper
module UsersHelper
def user_name_for(user)
user.name
end
end
crumb :user do |user|
link user_name_for(user), user
end
# I18n
crumb :home do
link t("breadcrumbs.home"), root_path
end
You can use the breadcrumbs
method directly as an array. It will return an array with the breadcrumb links so you can build the breadcrumbs HTML manually:
<% breadcrumbs.tap do |links| %>
<% if links.any? %>
You are here:
<% links.each do |link| %>
<%= link_to link.text, link.url, class: (link.current? ? "current" : nil) %> (<%= link.key %>)
<% end %>
<% end %>
<% end %>
If you use this approach, you lose the built-in semantic breadcrumb functionality. One way to add them back is to use JSON-LD structured data:
<script type="application/ld+json">
<%= raw breadcrumbs.structured_data(url_base: "https://example.com").to_json %>
</script>
Or, you can infer url_base
from request
:
<script type="application/ld+json">
<%= raw breadcrumbs.structured_data(url_base: "#{request.protocol}#{request.host_with_port}").to_json %>
</script>
If you want to add a link to the parent breadcrumb, you can use the parent_breadcrumb
view helper.
By default it returns a link instance that has the properties #key
, #text
, and #url
.
You can supply options like autoroot: false
etc.
If you supply a block, it will yield the link if it is present:
<% parent_breadcrumb do |link| %>
<%= link_to "Back to #{link.text}", link.url %>
<% end %>
When configuring breadcrumbs inside a crumb :xx do ... end
block, you have access to all methods that are normally accessible in the view where the breadcrumbs are inserted. This includes your view helpers, params
, request
, etc.
If you have a large site and you want to split your breadcrumbs configuration over multiple files, you can create a folder named config/breadcrumbs
and put your configuration files (e.g. products.rb
or frontend.rb
) in there.
The format is the same as config/breadcrumbs.rb
which is also loaded.
Breadcrumbs are automatically loaded from any engines' config/breadcrumbs.rb
and config/breadcrumbs/**/*.rb
.
Breadcrumbs defined in your main app will override breadcrumbs from engines.
Breadcrumbs can be automatically inferred if you pass an instance of an object that responds to model_name
(like an ActiveRecord model instance).
For example:
<% breadcrumb @product %>
is short for
<% breadcrumb :product, @product %>
You can pass options to links to be used when you render breadcrumbs manually.
In config/breadcrumbs.rb:
crumb :something do
link "My Link", my_path, title: "My Title", other: "My Other Option"
end
Example methods you can then use in the view:
breadcrumbs do |links|
links.each do |link|
link.title? # => true
link.title # => "My Title"
link.other? # => true
link.other # => "My Other Option"
link.nonexisting_option? # => false
link.nonexisting_option # => nil
end
end
You can improve the accessibility of your page with the markup that specified in ARIA. Gretel supports generating aria-current
attribute:
<% breadcrumb :issue, @issue %>
<%= breadcrumbs aria_current: "page" %>
This will generate the following HTML (indented for readability):
<div class="breadcrumbs">
<a href="/">Home</a> ›
<a href="/issues">All issues</a> ›
<span class="current" aria-current="page">My Issue</span>
</div>
- Full documentation
- Changelog
- Tutorial on using Gretel (Sitepoint)
Follows semantic versioning.
You are very welcome to help improve Gretel if you have suggestions for features that other people can use.
To contribute:
- Fork the project
- Create your feature branch (
git checkout -b my-new-feature
) - Make your changes
- Add/Fix tests
- Prepare database for testing:
cd spec/dummy; rake db:migrate; rake db:test:prepare; cd ../..
- Run
rake
to make sure all tests pass - Be sure to check in the changes to
coverage/coverage.txt
- Commit your changes (
git commit -am 'Add new feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new pull request
Thanks.
This repository had been a fork of lassebunk/gretel for a long time. However, due to some reasons, the maintenance of this repository was stopped and the official repository of gretel was transferred to WilHall/gretel, which is the fork of lassebunk/gretel. WilHall/gretel was then transferred to kzkn/gretel, where it continues to be maintained. During this time, kzkn/gretel was a fork of lassebunk/gretel, so lassebunk/gretel:master
was selected by default when a pull request was made. This caused unnecessary confusion for contributors to gretel.
As mentioned earlier, lassebunk/gretel is no longer maintained. I have decided to detach the fork for the future of gretel, with all due respect to @lassebunk for creating gretel.
Gretel was created by @lassebunk and was maintained by @WilHall. And it is maintained by @kzkn.
Have fun!
Copyright (c) 2010-2020 Lasse Bunk, released under the MIT license