[![Gem Version](https://badge.fury.io/rb/gretel.svg)](http://badge.fury.io/rb/gretel) ![](https://github.com/kzkn/gretel/workflows/CI/badge.svg) Handle breadcrumb trails... like a boss :) ([TL;DR](http://i.imgur.com/nH25yiH.png)) Gretel is a [Ruby on Rails](http://rubyonrails.org) 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](https://developers.google.com/search/docs/data-types/breadcrumb) (those used in Google results). Have fun! ## Installation In your *Gemfile*: ```ruby gem "gretel" ``` And run: ```bash $ bundle install ``` ## Example Start by generating breadcrumbs configuration file: ```bash $ rails generate gretel:install ``` Then, in *config/breadcrumbs.rb*: ```ruby # 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): ```erb <% breadcrumb :issue, @issue %> ``` Then, in *app/views/layouts/application.html.erb*: ```erb <%= breadcrumbs pretext: "You are here: ", separator: " › " %> ``` This will generate the following HTML (indented for readability): ```html ``` ## Options 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](https://developers.google.com/search/docs/data-types/breadcrumb). | 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 ### Styles 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 `
  • ` elements contained in an outer `
      `. `:ul` | Renders the links in `
    1. ` elements contained in an outer `
        `. `:bootstrap` | Renders the links for use in [Bootstrap v3](https://getbootstrap.com/docs/3.4/). `:bootstrap4` | Renders the links for use in [Bootstrap v4](https://getbootstrap.com/docs/4.6/getting-started/introduction/). `:bootstrap5` | Renders the links for use in [Bootstrap v5](https://getbootstrap.com/). `:foundation5` | Renders the links for use in [Foundation 5](https://get.foundation/). Or you can build the breadcrumbs manually for full customization; see below. If you add other widely used styles, please submit a [Pull Request](https://github.com/kzkn/gretel/pulls) so others can use them too. ## More examples In *config/breadcrumbs.rb*: ```ruby # 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 ``` ## Building the breadcrumbs manually 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: ```erb <% 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: ```erb ``` Or, you can infer `url_base` from `request`: ```erb ``` ## Getting the parent breadcrumb 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: ```erb <% parent_breadcrumb do |link| %> <%= link_to "Back to #{link.text}", link.url %> <% end %> ``` ## Nice to know ### Access to view methods 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. ### Using multiple breadcrumb configuration files 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. ### Loading breadcrumbs from engines 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. ### Inferring breadcrumbs 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: ```erb <% breadcrumb @product %> ``` is short for ```erb <% breadcrumb :product, @product %> ``` ### Passing options to links You can pass options to links to be used when you render breadcrumbs manually. In *config/breadcrumbs.rb*: ```ruby 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: ```ruby 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 ``` ### ARIA support You can improve the accessibility of your page with the markup that specified in [ARIA](https://www.w3.org/TR/wai-aria-practices/examples/breadcrumb/index.html). Gretel supports generating `aria-current` attribute: ```erb <% breadcrumb :issue, @issue %> <%= breadcrumbs aria_current: "page" %> ``` This will generate the following HTML (indented for readability): ```html ``` ## Documentation * [Full documentation](https://rubydoc.info/gems/gretel) * [Changelog](https://github.com/kzkn/gretel/blob/master/CHANGELOG.md) * [Tutorial on using Gretel](https://www.sitepoint.com/breadcrumbs-rails-gretel/) (Sitepoint) ## Versioning Follows [semantic versioning](https://semver.org/). ## Contributing You are very welcome to help improve Gretel if you have suggestions for features that other people can use. To contribute: 1. Fork the project 2. Create your feature branch (`git checkout -b my-new-feature`) 3. Make your changes 4. Add/Fix tests 5. Prepare database for testing: `cd spec/dummy; rake db:migrate; rake db:test:prepare; cd ../..` 6. Run `rake` to make sure all tests pass 7. Be sure to check in the changes to `coverage/coverage.txt` 8. Commit your changes (`git commit -am 'Add new feature'`) 9. Push to the branch (`git push origin my-new-feature`) 10. Create new pull request Thanks. ## Contributors Gretel was created by [@lassebunk](https://github.com/lassebunk) and was maintained by [@WilHall](https://github.com/WilHall). And it is maintained by [@kzkn](https://github.com/kzkn). [See the list of contributors](https://github.com/kzkn/gretel/graphs/contributors) ## And then After using Gretel, you'll be like this Have fun! Copyright (c) 2010-2020 [Lasse Bunk](http://lassebunk.dk), released under the MIT license