Tutorial for Adding Tabs to Rails Using Tabulous

Step-by-Step Tutorial for Creating a Tabbed Rails Application

This tutorial shows you how to make a simple Rails application from scratch that has both tabs and subtabs.

Update: This blog post is about an old version of tabulous. Tabulous 2 has a completely different syntax. This tutorial should still work except for the parts referring to the app/tabulous/tabulous.rb file. Read more about the new version of tabulous.

Step 1: Scaffolding the Application

Let’s say you want to keep track of all the fonts you like and all of the design-related websites you think are cool. And let’s also say that you don’t believe in using a simple text file but feel compelled to build an entire Rails app just for this purpose. (Who said this wasn’t going to be contrived?)

First, start by creating a Rails 3 app:

$ rails new contrived

And setting up its gems:

$ cd contrived
$ bundle install

And let’s add some scaffolding to keep track of our websites, serif fonts and sans serif fonts:

$ rails generate scaffold Website url:string
$ rails generate scaffold SerifFont name:string
$ rails generate scaffold SansSerifFont name:string

Now let’s hook up the root URL to point to the list of websites by adding this line to config/routes.rb:

  root :to => 'websites#index'

And remove the autogenerated index.html file:

$ rm public/index.html

Set up the database:

$ rake db:create
$ rake db:migrate

Now we are all set to fire up the app!

$ rails server

Navigating to http://localhost:3000 should show you something like this:

Step 2: Adding Tabs

Let’s use the ultrafantastically superb tabulous gem to add tabs to this app. Add the following to your app’s Gemfile:

gem 'tabulous'

And then

$ bundle install

Now type the following magical line:

$ rails generate tabs

which will create a file called app/tabs/tabulous.rb which comes included with wonderful explanatory comments, free of charge. Here’s what the file looks like without comments:

Tabulous.setup do |config|
 
  config.tabs do
    [
      #------------------------------------------------------------------------------------------------------------------------#
      #    TAB NAME                 |    DISPLAY TEXT          |    PATH                     |    VISIBLE?    |    ENABLED?    #
      #------------------------------------------------------------------------------------------------------------------------#
      [    :websites_tab            ,    'Websites'            ,    root_path                ,    true        ,    true        ],
      [    :websites_tab            ,    'Websites'            ,    websites_path            ,    true        ,    true        ],
      [    :serif_fonts_tab         ,    'Serif Fonts'         ,    serif_fonts_path         ,    true        ,    true        ],
      [    :sans_serif_fonts_tab    ,    'Sans Serif Fonts'    ,    sans_serif_fonts_path    ,    true        ,    true        ],
      #------------------------------------------------------------------------------------------------------------------------#
      #    TAB NAME                 |    DISPLAY TEXT          |    PATH                     |    VISIBLE?    |    ENABLED?    #
      #------------------------------------------------------------------------------------------------------------------------#
    ]
  end
 
  config.actions do
    [
      #----------------------------------------------------------------------------#
      #    CONTROLLER           |    ACTION          |    TAB                      #
      #----------------------------------------------------------------------------#
      [    :websites            ,    :all_actions    ,    :websites_tab            ],
      [    :websites            ,    :all_actions    ,    :websites_tab            ],
      [    :serif_fonts         ,    :all_actions    ,    :serif_fonts_tab         ],
      [    :sans_serif_fonts    ,    :all_actions    ,    :sans_serif_fonts_tab    ],
      #----------------------------------------------------------------------------#
      #    CONTROLLER           |    ACTION          |    TAB                      #
      #----------------------------------------------------------------------------#
    ]
  end
 
  config.active_tab_clickable = false
  config.always_render_subtabs = false
  config.raise_error_if_no_tab_found = true
  config.html5 = false
  config.css.scaffolding = true
  # config.css.background_color = '#ccc'
  # config.css.text_color = '#444'
  # config.css.active_tab_color = 'white'
  # config.css.hover_tab_color = '#ddd'
  # config.css.inactive_tab_color = '#aaa'
  # config.css.inactive_text_color = '#888'
 
end

You’ll notice that the file already has some tab data setup. Tabulous inspects your routes and tries to guess what tabs you may want, microsoft-clippy-style. Which means it gets it wrong. We really don’t need two websites tabs, so let’s delete one of them:

  config.tabs do
    [
      #------------------------------------------------------------------------------------------------------------------------#
      #    TAB NAME                 |    DISPLAY TEXT          |    PATH                     |    VISIBLE?    |    ENABLED?    #
      #------------------------------------------------------------------------------------------------------------------------#
      [    :websites_tab            ,    'Websites'            ,    websites_path            ,    true        ,    true        ],
      [    :serif_fonts_tab         ,    'Serif Fonts'         ,    serif_fonts_path         ,    true        ,    true        ],
      [    :sans_serif_fonts_tab    ,    'Sans Serif Fonts'    ,    sans_serif_fonts_path    ,    true        ,    true        ],
      #------------------------------------------------------------------------------------------------------------------------#
      #    TAB NAME                 |    DISPLAY TEXT          |    PATH                     |    VISIBLE?    |    ENABLED?    #
      #------------------------------------------------------------------------------------------------------------------------#
    ]
  end
 
  config.actions do
    [
      #----------------------------------------------------------------------------#
      #    CONTROLLER           |    ACTION          |    TAB                      #
      #----------------------------------------------------------------------------#
      [    :websites            ,    :all_actions    ,    :websites_tab            ],
      [    :serif_fonts         ,    :all_actions    ,    :serif_fonts_tab         ],
      [    :sans_serif_fonts    ,    :all_actions    ,    :sans_serif_fonts_tab    ],
      #----------------------------------------------------------------------------#
      #    CONTROLLER           |    ACTION          |    TAB                      #
      #----------------------------------------------------------------------------#
    ]
  end

Let’s look at these two tables in more detail. The first table is where you define your tabs. The order that you define them in is the order that they appear in the view. The columns contain Ruby expressions that are evaluated in the context of a Ruby view (which is why we can use route helpers). The second table is necessary so that when a controller action is called we know what tab should be selected. :all_actions is a shortcut; you can explicitly list actions out, one on each row.

The next thing we need to do is tell tabulous where in the view the tabs should be rendered. Tabulous gives us two view helpers: tabs and subtabs. Open up your app/views/layouts/application.html.erb file and add them like so:

<!DOCTYPE html>
<html>
<head>
  <title>Contrived</title>
  <%= stylesheet_link_tag :all %>
  <%= javascript_include_tag :defaults %>
  <%= csrf_meta_tag %>
</head>
<body>
 
<%= tabs %>
<%= subtabs %>
<%= yield %>
 
</body>
</html>

Restart your Rails server and reload http://localhost:3000 in your browser. You should see something like this:

And there you have it. Tabs in Rails! That wasn’t so hard, was it?

Notice that the tabs are styled for you. Tabulous adds CSS scaffolding to get you started but you should eventually turn off the scaffolding and use your own CSS. If you view the HTML source you can see the CSS that tabulous generated which can give you a head start.

Step 3: Adding Subtabs

What you really want is to have a fonts tab with two subtabs: serif and sans serif. To do that, change your app/tabs/tabulous.rb file to the following:

  config.tabs do
    [
      #---------------------------------------------------------------------------------------------------------------------#
      #    TAB NAME                    |    DISPLAY TEXT    |    PATH                     |    VISIBLE?    |    ENABLED?    #
      #---------------------------------------------------------------------------------------------------------------------#
      [    :websites_tab               ,    'Websites'      ,    websites_path            ,    true        ,    true        ],
      [    :fonts_tab                  ,    'Fonts'         ,    serif_fonts_path         ,    true        ,    true        ],
      [    :serif_fonts_subtab         ,    'Serif'         ,    serif_fonts_path         ,    true        ,    true        ],
      [    :sans_serif_fonts_subtab    ,    'Sans Serif'    ,    sans_serif_fonts_path    ,    true        ,    true        ],
      #---------------------------------------------------------------------------------------------------------------------#
      #    TAB NAME                    |    DISPLAY TEXT    |    PATH                     |    VISIBLE?    |    ENABLED?    #
      #---------------------------------------------------------------------------------------------------------------------#
    ]
  end
 
  config.actions do
    [
      #-------------------------------------------------------------------------------#
      #    CONTROLLER           |    ACTION          |    TAB                         #
      #-------------------------------------------------------------------------------#
      [    :websites            ,    :all_actions    ,    :websites_tab               ],
      [    :serif_fonts         ,    :all_actions    ,    :serif_fonts_subtab         ],
      [    :sans_serif_fonts    ,    :all_actions    ,    :sans_serif_fonts_subtab    ],
      #-------------------------------------------------------------------------------#
      #    CONTROLLER           |    ACTION          |    TAB                         #
      #-------------------------------------------------------------------------------#
    ]
  end

Notice how subtabs’ names must end in _subtab. Also notice how the subtabs immediately follow the tab that groups them. Finally, notice in the actions section how we hooked up the controllers to the subtabs. For example, when an action of the SerifFontsController is rendered, the :serif_fonts_subtab will be selected. Since tabulous knows that the :fonts_tab is its parent, the :fonts_tab will also appear selected.

After you edit the tabulous.rb file you may notice the tables are all out of alignment. To prettify the file:

$ rake tabs:format

Refresh your browser. When you click on the “Fonts” tab you should now see subtabs like this:

The markup that’s generated looks like this:

<div id="tabs">
  <ul>
    <li class="inactive enabled"><a href="/websites" class="tab">Websites</a></li>
    <li class="active enabled"><span class="tab">Fonts</span></li>
  </ul>
</div>
<div id="subtabs">
  <ul>
    <li class="active enabled"><span class="tab">Serif</span></li>
    <li class="inactive enabled"><a href="/sans_serif_fonts" class="tab">Sans Serif</a></li>
  </ul>
</div>

Step 4: Profit!

There are many other things that tabulous can do, such as support HTML5 and disabled tabs. The best place to learn about the full capabilities of tabulous is to read the comments in the app/tabs/tabulous.rb file after you generate it.

You can also watch my live demo of tabulous that I presented to the Boston Ruby Group. They asked some really good questions.

Happy tabbing!

You can skip to the end and leave a response. Pinging is currently not allowed.

51 Responses to “Tutorial for Adding Tabs to Rails Using Tabulous”

  1. Miguel says:

    I’m working with bootstrap tabs and i generate dynamic tabs with javascript, but if i want to implement tabs with devise and i want to config some user can open this tabs and this other user open another this tab. What is the best way to do that?

Leave a Reply