17

I'm slightly insecure about my breadcrumb solution. Names and links are defined in each controller action:

<a href="http://localhost:3000/">Home</a>
<% if defined? @l1_link %>
  > <a href="<%= @l1_link%>"><%= @l1_name %></a>
  <% if defined? @l2_link %>
    > <a href="<%= @l2_link%>"><%= @l2_name %></a>
  <% end %>
<% end %>

This way I can use:

@l1_link = user_path()

Question: As I am not that smart - could this kind of system lead to desaster somewhere down the road? Is this (grossly) inefficient?

johannes
  • 7,262
  • 5
  • 38
  • 57
Michael Schmitz
  • 1,074
  • 2
  • 12
  • 27
  • Hi, thanks for the answers @Simone - I like your solution, never thought about DRY-ing by moving the definition before my actions. I'll take that right away. @Lolindrath - Yes, the split is nice, however my app is not clean enough (and names change, and i18n etc...) @Christopher: Got to check the episode, didn't get remark 3. (why full-blown objects?), but Nr. 2 is definitely something I need to think about. Thanks! – Michael Schmitz Feb 18 '10 at 19:30
  • Here are two approaches: [Split the URL and display it](https://stackoverflow.com/questions/555669/easy-breadcrumbs-for-restful-rails-application) A more flexible solution implemented in the controller where you setup the breadcrumbs in the controller: [Easy and Flexible Breadcrumbs for Rails](http://szeryf.wordpress.com/2008/06/13/easy-and-flexible-breadcrumbs-for-rails/) – Lolindrath Feb 17 '10 at 13:12

6 Answers6

32

Breadcrumbs menu are a recurrent pattern in most Rails applications. To solve this issue, I created and released a plugin called breadcrumbs_on_rails.

You define your breadcrumbs in the controller

class MyController

  add_breadcrumb "home", root_path
  add_breadcrumb "my", my_path

  def index
    # ...

    add_breadcrumb "index", index_path
  end

end

and you render them in your view.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  <title>untitled</title>
</head>

<body>
  <%= render_breadcrumbs %>
</body>
</html>

Even if you don't want to use a plugin, I encourage you to give it a look. It's open source and you can grab some idea for your app.

Simone Carletti
  • 173,507
  • 49
  • 363
  • 364
  • 1
    This is good, but breadcrumbs seem like a view responsibility instead of a controller responsibility. I'd recommend moving the add_breadcrumb method call to your view. – Ben Crouse Feb 17 '10 at 13:22
  • 6
    You can call the method in your controller as well in your view. The controller allows you to define a per-controller navigation level to reduce code duplication in your views. – Simone Carletti Feb 17 '10 at 14:13
14

I made a gem named Gretel that is a Ruby on Rails plugin for creating breadcrumbs. The breadcrumbs are configured in a separate configuration file and selected in the view.

Example config/breadcrumbs.rb:

crumb :root do
  link "Home", root_path
end

crumb :projects do
  link "Projects", projects_path
end

crumb :project do |project|
  link project.name, project_path(project)
  parent :projects
end

crumb :project_issues do |project|
  link "Issues", project_issues_path(project)
  parent :project, project
end

crumb :issue do |issue|
  link issue.name, issue_path(issue)
  parent :project_issues, issue.project
end

In your view:

<% breadcrumb :issue, @issue %>

In your app/views/layouts/application.html.erb:

<%= breadcrumbs pretext: "You are here: " %>
Lasse Bunk
  • 1,848
  • 20
  • 21
  • 1
    Thank you for the gem, just tried to add it and I get this "wrong number of arguments (1 for 0)". Any help would be appreciated! Best, Alex – Alexandru Paduraru Sep 01 '16 at 13:23
12

This is mostly a matter of opinion, but anyway:

  1. I would not want that much logic in a view. We've probably all done it, but it gets messy quickly.
  2. The code is not safe against future changes that affect the depth of the tree.
  3. Instead of linked variables *_name and *_link, I'd suggest using proper objects anyway, with some link_to functionality.

You might find Episode 162 of Railscasts of interest for a nice solution that gets by with

<% for page in @page.ancestors.reverse %>
  <%= link_to h(page.name), page %> &gt;
<% end %>
Christopher Creutzig
  • 8,656
  • 35
  • 45
  • That rails cast has been updated. [#162 Tree-Based Navigation (revised)](http://railscasts.com/episodes/162-tree-based-navigation-revised) – rosalynnas Jun 25 '19 at 22:22
5

Do not use any plugins just for breadcrumbs. This link provides an efficient method to generate breadcrumbs.

http://szeryf.wordpress.com/2008/06/13/easy-and-flexible-breadcrumbs-for-rails/

Although, it is a very old post, it still works.

BookOfGreg
  • 3,550
  • 2
  • 42
  • 56
user1449337
  • 1,003
  • 1
  • 8
  • 8
1

I did a fork of crumble gem. It has very few configuration options and it appears abandoned, but when I tried to switch to breadcrumbs_on_rails or gretel, I realized that I have to add many lines to my views or controllers (and I have a lot of them), but with crumble it is all stored in one configuration file. If you like to do some patches and prefer configuration in one place, I think it is the best solution ever.

sekrett
  • 1,205
  • 1
  • 15
  • 17
1

You could also use Ariane http://github.com/simonc/ariane

With it you can generate any kind of breadcrumb, as links in a paragraph or as a ul/li :)

If you want something specific, you can create your own renderer.

It's pretty simple to use, just add this in a before_filter:

ariane.add 'Home', root_path # in the app controller to have it everywhere
ariane.add 'Some Page', some_path
Happynoff
  • 1,365
  • 1
  • 14
  • 28