TabsOnRails: creating and managing Tabs with Ruby on Rails

April 25th, 2009 at 2:42 pm • permalink27 comments

TabsOnRails is a simple Rails plugin for creating and managing Tabs. It provides helpers for creating tabs with a flexible interface.

If you ever had to create a tab-based navigation menu at least once, you perfectly know how much it can annoying. You have to create the menu, set active status in your controllers and reflect selection status in your view. TabsOnRails does all the boring stuff for you and let you focus on the customization.

Let me show you how it works.

Quick Start

In your template use the tabs_tag helper to create your tab.

<%= tabs_tag do |tab| %>
  <%= tab.home       'Homepage', root_path %>
  <%= tab.dashboard  'Dashboard', dashboard_path %>
  <%= tab.account    'Account', account_path %>
<% end %>

The example above produces the following HTML output.

<ul>
  <li><a href="/">Homepage</a></li>
  <li><a href="/dashboard">Dashboard</a></li>
  <li><a href="/account">Account</a></li>
</ul>

The usage is similar to the Rails route.rb file. You create named tabs with the syntax tab.name_of_tab. The name you use creating a tab is the same you’re going to refer to in your controller when you want to flag the tab as active with current_tab.

class DashboardController < ApplicationController
  current_tab :dashboard
end

Now, for any action defined in the DashboardController, the template will automatically render the following HTML code.

<ul>
  <li><a href="/">Homepage</a></li>
  <li><span>Dashboard</span></li>
  <li><a href="/account">Account</a></li>
</ul>

Restricting current_tab scope

Off course, there are specific situations where you need to change current_tag only for some specific action in your controller.

The current_tab method understands all options you are used to pass to a Rails controller filter. In fact, behind the scenes this method uses a before_filter to set a special @current_tab variable. Taking advantage of Rails filter options, you can restrict a tab to a selected group of actions in the same controller.

class PostsController < ApplicationController
  current_tab :admin
  current_tab :posts, :only => [ :index, :show ]
end

class ApplicationController < ActionController::Base
  current_tab :admin, :if => :admin_controller?

  def admin_controller?
    self.class.name =~ /^Admin(::|Controller)/
  end
end

Customizations

All your tabs belongs to you! Easily to understand, your tab structure might be slightly different that the default one. For example, you might want to flag the active tab with a current CSS class and preserve the link with a nice hover effect. Or perhaps your tab is an ordered list (<ol>).

No problem! The library is completely customizable using custom builders. See the documentation for further details on how to create and use a custom Tab Builder.

Here’s just a couple of examples created using custom builders.

tab-example11

tab-example2

Cool! How do I get the plugin?

Source code and issue management is powered by GitHub, the project homepage and documentation are hosted on this site. The plugin is available both as a GEM and as a Rails plugin. See the documentation page to learn how to install it.

  1. TabsOnRails 0.3.0 with concurrent tabs support aka namespaces
  2. TabsOnRails graduated from beta
  3. TabsOnRails 0.8.0
  4. TabsOnRails 2.0.0
  5. Capistrano: Managing an uploads folder

Filed in Programming • Tags: , , , , , ,

Comments

remco says:

Hi Simone,

I just installed your plugin and folllowed the setup. After booting and fire-up my browser i get this message:

ActionView::TemplateError (wrong number of arguments (1 for 2)) on line #1 of pages/_menu.rhtml:
1:
2:
3:

Can you help me?

Thanks..

Grtz..remco

Simone says:

Post me the code you are using to build the menu.
I see you named the file .rhtml. Which version of Rails powers your project?

remco says:

Thanks..for the quick reply…

Rails 2.3.2

ActionView::TemplateError (wrong number of arguments (1 for 2)) on line #1 of pages/_menu.rhtml:

1:
2:
3:

remco

Simone says:

The code seems to be right. If you look at the test, it is more or less the same piece of code.

< % tabs_tag do |tabs| %>
  < %= tabs.dashboard 'Dashboard', '/d' %>
  < %= tabs.welcome 'Welcome', '/w' %>
< % end -%>

Could you pastie the full exception backtrace? Did you change something or did you create any custom Builder?

remco says:

i did not change anything…i just installed you’re plugin and followed the guide.

I am a newbie in RoR, but i think it has todo that the code (helper_file) is not loaded. So the tabs_tag object stays empty.

full error message:
http://www.pastie.org/497699

remco

Simone says:

Before I asked you which Rails version you are using and you answered Rails 2.3.2. However, it seems you are using Rails 2.1.0 instead (see actionpack-2.1.0).
My plugin requires Rails >= 2.2.0 due to some incompatible changes in the concat method API from Rails 2.1.0 to Rails 2.2.0 and above.

remco says:

When i do this in my console

rails -v,

this is the output.

Rails 2.3.2

Simone says:

It means your most recent installed version is 2.3.2 but it doesn’t necessary mean you are using it.
Check your environment.rb file and your passenger configuration and make sure to use Rails 2.3.2. As I show you before, your project is running Rails 2.1.0.

Chris says:

Hi Simone,

How would I render a partial with your plugin? This might be a noob question, just can’t figure it out. Here’s my code…

‘readings’) %>

I’ve tried several variation of the render syntax. If I figure it out before you get to my question I post my solution.

Thanks,
Chris

Chris,
WordPress sanitized your code. Please use Pastie or a similar tool to show the code fragment.

Maarten O. says:

Nice clean implementation of tabs in rails. I started using it instead of the more complex tabnav generator in Rails Widgets. However I’d prefer active tabs to remain clickable, allowing the user to return to the tab link from nested pages.

Hi Maarten,
you can easily customize the behavior creating a custom builder.

In your case, simply extend TabsBuilder and overwrite tab_for.

class MyTabsBuilder < TabsOnRails::Tabs::TabsBuilder

  def tab_for(tab, name, options)
    content = @context.link(current_tab?(tab), name, options) do
      @context.content_tag(:span, name)
    end
    @context.content_tag(:li, content)
  end

end
Maarten O. says:

Yes indeed. I did the following.

    def tab_for(tab, name, options)
       content = @context.link_to(name, options)
        if current_tab?(tab)
          @context.content_tag(:li, content, :class => 'active')
        else
          @context.content_tag(:li, content)
        end
      end

Thanks again.

Mr Y says:

u did not teach where to put this

class MyTabsBuilder < TabsOnRails::Tabs::TabsBuilder

ppl like me have no idea where to put that code.

You can write it in the application helper file.

Ivan Fragoff says:

With my CustomTabsBuilder defined in ApplicationHelper module and passed to tabs_tag(:builder => CustomTabsBuilder) I’m getting the following:
uninitialized constant ActionView::CompiledTemplates::CustomTabsBuilder

Am I missing a step?

If you defined the builder inside ApplicationHelper and you are calling tabs_tag outside the helper, you need to pass the full qualified module name.

tabs_tag(:builder => ApplicationHelper::CustomTabsBuilder)
erwin says:

Hi , first of all thanks for your excellent work …it’s working helping me a lot
I juts want to check if the following warning during execution could be linked to your code or mine …

DEPRECATION WARNING: - style block helpers are deprecated. Please use =. (called from _app_views_clips_index_html_haml___942455032782073570_2219357180__3927923673637500760 at /Users/yves/Sites/rails/testsbga/app/views/clips/index.html.haml:27)

line 27 =>   - tabs_tag :open_tabs => { :id => "tabs", :class => "tabbar" } do |tab|
			  = tab.myMemberships I18n.t(:my_membership, :count => @memberships.count), memberships_path
			  = tab.myClips I18n.t(:my_clips), clips_path
			  = tab.myComparisons I18n.t(:my_comparisons), comparisons_path
			  = tab.myAnalyses I18n.t(:my_analyses), analyses_path
			  = tab.myPayments I18n.t(:my_payments), payments_path

which is generating correctly the following html

              My Membership
              My Clips
              My Comparisons
              My Analyses
              My Payments

any clue ?

- tabs_tag should be = tabs_tag

Phil says:

Hi Simon. I am new to RubyOnRails, and have to build a simple web app for a school project. This seems like the perfect plugin since I am trying to make the app display a few tabs, but I am having difficulties implementing this as I essentially know very little about rails, and the tutorials aren’t helpful enough. Can you provide a basic explanation of how to use your plugin? (i.e., where would the different samples you give above be placed in an app). Thanks.

The plugin documentation contains examples and information about how to use it.
http://www.simonecarletti.com/code/tabs_on_rails/docs.html

kritzy says:

Hi, I’m new to ruby on rails. I tried implementing the example you put up, but I’m running into this error: “undefined local variable or method `dashboard_path’ for #<#:0x3ff37b0>”
What does this mean? Any help would be appreciated.

dashboard_path is an example of route. You need to use your application routes.

manoj menon says:

very hepful to understand about the menu.

Ivan says:

Hi, does it come with any default CSS? I installed it and it shows just as an unordered list in the browser, not really as tabs.
Also, the link to”how to create and use a custom Tab Builder.” above gives 404!

Thanks

Ivan

No, it doesn’t provide any CSS. This is not a CSS class to build interfaces. Consider to use jQuery UI or Twitter bootstrap if you need such feature.

Add a Comment




Follow Me
    Random Quote