Generating your site menu with the 'simple-navigation' gem

January 3, 2012


This post was originally published in the Rambling Labs Blog on January 3, 2012.


One of the cool things I learned while building our new site was how to generate your site navigation menu without having to do the highlighting logic yourself.

There’s a great gem out there for this called simple-navigation, which you can find on GitHub. It’s easy to set up and use, so you will probably do what you need to do really quick. To install, add it to your rails application Gemfile:

gem 'simple-navigation'

Then, run bundle install. After it’s installed, generate the configuration file for it, which will be the config/navigation.rb, with the following:

rails generate navigation_config

Go ahead and open the config/navigation.rb file, and add your navigation items, which in my case is the following:

SimpleNavigation::Configuration.run do |navigation|
  navigation.selected_class = 'current'
  navigation.items do |primary|
    primary.item :menu_home, 'Home', root_path
    primary.item :menu_about_us, 'About Us', about_us_path
    primary.item :menu_blog, 'Blog', posts_path
    primary.item :menu_contact_us, 'Contact Us', contact_us_path
  end
end

As you may have noticed, I don’t have to specify when to be highlighted. This is because the gem assumes, by convention, that each navigation item will only be highlighted when its url matches the current url being accessed. Great! That’s less navigation code for me to write.

Ah, but wait, I want my blog navigation item to be highlighted whenever your accessing any url under /blog. Fair enough, simple-navigation supports a highlights_on option, which can be passed either a regular expression to match with the current url or a lambda that will determine if it’s highlighted. I changed the blog navigation to this:

  navigation.items do |primary|
    # ...
    primary.item :menu_blog, 'Blog', posts_path, highlights_on: /\/blog/
    # ...
  end

Where they completely bought me in was with the navigation rendering. To render your navigation menu, just write this:

<%= render_navigation %>

And that’s it! Awesome, right?

In case you want to define navigation levels, just pass a block to the primary.item definition, like this:

  navigation.items do |primary|
    # ...
    primary.item :menu_blog, 'Blog', posts_path, highlights_on: /\/blog/ do |blog|
      blog.item :menu_popular, 'Popular', popular_posts_path
      blog.item :menu_recent, 'Recent', recent_posts_path
    end
    # ...
  end

You can find more documentation on the simple navigation’s wiki

Enjoy! :)