TabsOnRails: Creating and managing Tabs with Ruby on Rails¶
- TabsOnRails: Creating and managing Tabs with Ruby on Rails
- Requirements
- Rails Installation
- As a Gem
- As a Plugin
- Quick Start
- Restricting set_tab scope
- Using Namespaces to create Multiple Tabs
- Rendering Tabs with Namespaces
- Namespace scope
- Tab Builders
- Understanding the Builder
- Creating a custom Builder
- Using a custom Builder
- Author
- Resources
- License
TabsOnRails is a simple Rails plugin for creating and managing Tabs. It provides helpers for creating tabs, an navigation menu in general, with a flexible interface.
Requirements¶
- Ruby >= 1.8.6
- Rails >= 2.2
Note. TabsOnRails doesn't work with Rails 2.1 or previous versions (see #245).
Rails Installation¶
As a Gem¶
This is the preferred way to install TabsOnRails and the best way if you want install a stable version.
The GEM is hosted on Gemcutter.
1 $ gem install tabs_on_rails --source http://gemcutter.org
With Rails >= 2.2, you can specify the GEM dependency in your environment.rb file so that Rails will automatically check the requirement on startup.
1 Rails::Initializer.run do |config|
2
3 # other configurations
4 # ...
5
6 config.gem "tabs_on_rails", :source => "http://gemcutter.org"
7
8 end
As a Plugin¶
This is the preferred way if you want to live on the edge and install a development version.
1 $ script/plugin install git://github.com/weppos/tabs_on_rails.git
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.
1 <ul>
2 <li><a href="/">Homepage</a></li>
3 <li><a href="/dashboard">Dashboard</a></li>
4 <li><a href="/account">Account</a></li>
5 </ul>
The usage is similar to the Rails route 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 mark a tab as the current tab.
1 class DashboardController < ApplicationController
2 set_tab :dashboard
3 end
Now, for every action defined in DashboardController, the template will automatically render the following HTML code.
1 <ul>
2 <li><a href="/">Homepage</a></li>
3 <li><span>Dashboard</span></li>
4 <li><a href="/account">Account</a></li>
5 </ul>
Use the current_tab helper method if you need to access the value of current tab in your controller or template.
class DashboardController < ApplicationController set_tab :dashboard end # In your view <p>The name of current tab is <%= current_tab %>.</p>
The open_tag can be customized with the :open_tabs option.
<% tabs_tag :open_tabs => { :id => "tabs", :class => "cool" } do |tab| %>
<%= tab.home 'Homepage', root_path %>
<%= tab.dashboard 'Dashboard', dashboard_path %>
<%= tab.account 'Account', account_path %>
<% end %>
<ul id="tabs" class="cool">
<li><a href="/">Homepage</a></li>
<li><a href="/dashboard">Dashboard</a></li>
<li><a href="/account">Account</a></li>
</ul>
Further customizations require a custom Builder (see below).
Restricting set_tab scope¶
The set_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 store the tab in the @tab_stack variable.
Taking advantage of Rails filter options, you can restrict a tab to a selected group of actions in the same controller.
1 class PostsController < ApplicationController
2 set_tab :admin
3 set_tab :posts, :only => %w(index show)
4 end
5
6 class ApplicationController < ActionController::Base
7 set_tab :admin, :if => :admin_controller?
8
9 def admin_controller?
10 self.class.name =~ /^Admin(::|Controller)/
11 end
12 end
Using Namespaces to create Multiple Tabs¶
Namespaces enable you to create and manage tabs in parallels. The best way to demonstrate namespace usage is with an example.
Let's assume your application provide a first level navigation menu with 3 elements: :home, :dashboard, :projects. The relationship between your tabs and your controllers is 1:1 so you should end up with the following source code.
1 class HomeController
2 set_tab :home
3 end
4
5 class DashboardController
6 set_tab :dashboard
7 end
8
9 class ProjectsController
10 set_tab :projects
11
12 def first; end
13 def second; end
14 def third; end
15 end
The project controller contains 3 actions and you might want to create a second-level navigation menu. This menu should reflect the navigation status of the user in the project page.
Without namespaces, you wouldn't be able to accomplish this task because you already set the current tab value to :projects. You need to create a parallel navigation menu and uniquely identify it with a custom namespace.
Let's call it :navigation.
1 class ProjectsController
2 set_tab :projects
3
4 # Create an other tab navigation level
5 set_tab :first, :navigation, :only => %w(first)
6 set_tab :second, :navigation, :only => %w(second)
7 set_tab :third, :navigation, :only => %w(third)
8
9 def first; end
10 def second; end
11 def third; end
12 end
VoilĂ ! That's all you need to do. And you can create an unlimited number of namespaces as long as you use an unique name to identify them.
The default namespace is called :default. Passing :default as namespace name is the same as don't using any namespace at all. The following lines are equivalent.
1 set_tab :projects
2 set_tab :projects, :default
Rendering Tabs with Namespaces¶
To switch namespace in your template, just pass the :namespace option to the tabs_tag helper method.
1 <% tabs_tag do |tab| %>
2 <%= tab.home 'Homepage', root_path %>
3 <%= tab.dashboard 'Dashboard', dashboard_path %>
4 <%= tab.projects 'Projects', projects_path %>
5 <% end %>
6
7 <% tabs_tag :namespace => :navigation do |tab| %>
8 <%= tab.first 'First', first_project_path %>
9 <%= tab.second 'Second', second_project_path %>
10 <%= tab.third 'Account', third_project_path %>
11 <% end %>
Namespace scope¶
As a bonus feature, the namespace needs to be unique within current request scope, not necessarily across the entire application.
Back to the previous example, you can reuse the same namespace in the other controllers. In this way, you can reuse your templates as well.
1 class HomeController
2 set_tab :home
3 end
4
5 class DashboardController
6 set_tab :dashboard
7
8 set_tab :index, :navigation, :only => %w(index)
9 set_tab :common, :navigation, :only => %w(foo bar)
10
11 # ...
12 end
13
14 class ProjectsController
15 set_tab :projects
16
17 set_tab :first, :navigation, :only => %w(first)
18 set_tab :second, :navigation, :only => %w(second)
19 set_tab :third, :navigation, :only => %w(third)
20
21 # ...
22 end
Tab Builders¶
The Builder is responsible for creating the tabs HTML code. This library is bundled with two Builders:
Tabs::Builder: this is the abstract interface for any custom builder.Tabs::TabsBuilder: this is the default builder.
Understanding the Builder¶
Builders act as formatters. A Builder encapsulates all the logic behind the tab creation including the code required to toggle tabs status.
When the tabs_tag helper is called, it creates a new Tabs instance with selected Builder.
If you don't provide a custom builder, then Tabs::TabsBuilder is used by default.
Creating a custom Builder¶
All builders must extend the base Tabs::Builder class and implement at least the tab_for method.
Additional overridable methods include:
open_tabs: the method called before the tab setclose_tabs: the method called after the tab settab_for: the method called to create a single tab item
The following example creates a custom tab builder called MenuTabBuilder.
1 class MenuTabBuilder < TabsOnRails::Tabs::Builder
2 def tab_for(tab, name, options, item_options = {})
3 item_options[:class] = (current_tab?(tab) ? 'active' : '')
4 @context.content_tag(:li, item_options) do
5 @context.link_to(name, options)
6 end
7 end
8 end
Using a custom Builder¶
In your view, simply pass the builder class to the tabs_tag method.
<% tabs_tag(:builder => MenuTabBuilder) do |tab| %> <%= tab.home 'Homepage', root_path %> <%= tab.dashboard 'Dashboard', dashboard_path %> <%= tab.account 'Account', account_path, :style => 'float: right;' %> <% end %>
This is the final result.
<ul> <li class=""><a href="/">Homepage</a></li> <li class="active"><a href="/dashboard">Dashboard</a></li> <li class="" style="float: right;"><a href="/account">Account</a></li> </ul>
Author¶
Resources¶
License¶
Copyright (c) 2009 Simone Carletti, TabsOnRails is released under the MIT license.