Is there any helper method (Other than default rails breadcrumb) that generates bread crumb navigation dynamically for a particular page without having to pass trivial parameters in RESTful application? That is, something that figures out automatically where the user is based on the REST url she is visiting?
For above mentioned implementation, we need to pass parameters like
REST
<% add_crumb(‘Profile’, user_profile_path) %>
Current page
<% add_crumb(“My Incoming Messages”, request.path) %>
There must be a way to generalize the code so that no parameter passing is required and should work for all RESTful apps with minimal configuration.
Developed a simple hack. The method however assumes that there exists a method 'name' for every model object corresponding to each resource in the RESTful url. Whatever that the method 'name' returns is shown as breadcrumb name. If it is not found, it is shown as it is without making it link to anything. Separator used is '->' You may change it to suit your requirement.
def get_bread_crumb(url)
begin
breadcrumb = ''
sofar = '/'
elements = url.split('/')
for i in 1...elements.size
sofar += elements[i] + '/'
if i%2 == 0
begin
breadcrumb += "<a href='#{sofar}'>" + eval("#{elements[i - 1].singularize.camelize}.find(#{elements[i]}).name").to_s + '</a>'
rescue
breadcrumb += elements[i]
end
else
breadcrumb += "<a href='#{sofar}'>#{elements[i].pluralize}</a>"
end
breadcrumb += ' -> ' if i != elements.size - 1
end
breadcrumb
rescue
'Not available'
end
end
The method generally accepts request.url (Which given url of the current page) as the parameter. The method purposefully accepts the url for customization purposes. To generate the breadcrumb, simply add following code in your view -
<%= get_bread_crumb(request.url) %>
For the url /ideabox/2/idea/1
, the bread crumb looks like
alt text http://www.imagechicken.com/uploads/1234855404069992300.png
Excuse me if code quality is not that great. I'm sure this code can be re-factored but I'm also sure you would be able to do that before using it.
Thanks.
The solution provided by chirantan is great. If you need breabcrumbs for namespaced controller and need to change the breadcrumbs depending on the namespace as well then try this. This is not perfect but refactor it as you need. It works for my project.
Define a new helper: navigation_helper.rb
module NavigationHelper
def navigation_add(title, url, namespace)
if defined? @@namespace and !@@namespace.nil? and @@namespace == namespace
@@navigation ||= []
else
@@navigation = []
end
@@navigation << {title: title, url: url} unless title == "Home"
new_nav = []
@@navigation.each do |hash|
new_nav.push hash
if hash[:title].to_s == title.to_s
break
end
end
@@navigation = new_nav
@@navigation.uniq!
@@namespace = namespace
end
def render_navigation
if (request.path_parameters[:controller].sub('/', '::_').camelize + 'Controller').classify.constantize.action_methods.to_a.include? 'index'
navigation_add controller_name.camelize.to_s, request.path_parameters.merge({action: 'index'}).except(:id), params[:controller].include?('/') ? params[:controller].split("/").first : nil
end
if defined? @@navigation
render partial: 'navigation/navigation', locals: { navs: @@navigation, namespace: @@namespace }
else
render text: ''
end
end
end
Then define a view for this helper _navigation.haml
- unless navs.blank?
%ol.breadcrumb
- navs.each_with_index do |nav, index|
- if index == 0
%li=link_to fa_icon('arrow-left', text: 'Go Back'), :back
- unless namespace.nil?
%li
%h4.inline= request.fullpath.split('/')[1].gsub('-', '_').camelize
= fa_icon('angle-double-right')
%li= link_to_unless (nav[:title] == controller_name.camelize and action_name == 'index'), fa_icon(nav[:title].downcase.singularize, text: nav[:title]), nav[:url]