Too good to be true! Twitter Bootstrap meets Formtastic and Tabulous

This entry is part 2 of 3 in the series Twitter Bootstrap and Rails

Twitter Bootstrap and Rails

This simple 5 step tutorial will create a workingRails 3.1 app using Twitter Bootstrap

Last month I discussed all of the different gems that are available for integrating Twitter Bootstrap with a Rails 3.1 app. These gems make the Twitter Bootstrap CSS styles available in your Rails 3.1 asset pipeline as Less or Sass code. However, getting the Twitter CSS code is just the first step – you also need to know how to use it in a Rails app.

Today I’ll take the next step. This article is a detailed, step by step tutorial that will take you through the process of writing a new Rails 3.1 app that uses Twitter Bootstrap with Formtastic and Tabulous, two great gems that make it easier to implement web forms and tab based navigation in Rails – two major features of Twitter Bootstrap. We’ll also use a third gem called Formtastic-Bootstrap that modifies the HTML produced by Formtastic to play nicely with the Twitter Bootstrap files.

Read on to learn more… in just five easy steps we’ll have a simple web site up and running that illustrates how to implement Twitter Bootstrap forms and tab navigation using Rails 3.1!

Step 1: Create a new Rails app

Let’s get started by creating a brand new Rails 3.1.3 app, the latest version of Rails available as I write this:

$ rails -v
Rails 3.1.3
$ rails new origami_hub
$ cd origami_hub
$ rm public/index.html
$ rails generate controller welcome index

You can see we’re going to create a web site to keep track of Origami artwork! You can also see I deleted the default, static home page, public/index.html. And the last command generates a controller called “Welcome” that will handle displaying the web site’s home page.

The next step is to edit the config/routes.rb file. Go ahead and paste this into the routes file:

OrigamiHub::Application.routes.draw do
  root :to => 'welcome#index'
end

Finally, let’s start up our Rails server (type “rails server”) and open http://localhost:3000:

Default page created by rails controller generator

You should see this text in the site’s new home page; if you don’t then double check the commands above carefully.

Step 2: Add Bootstrap-Sass

Today I’ll use the Bootstrap-Sass gem by Thomas McDonald to import the Twitter Bootstrap code. To learn more about Bootstrap-Sass and how it works, check out my post from November. Adding it to our new Rails app is simple; first edit your Gemfile and add it to the “assets” group:

# Gems used only for assets and not required
# in production environments by default.
group :assets do
  gem 'bootstrap-sass'

etc...

Then you need to install it with Bundler:

$ bundle install

Next, we need to create a new Sass code file to hold our CSS style code. Create a file called “origami_hub.css.scss” in the app/assets/stylesheets folder with this one line of code in it. This imports the Twitter Bootstrap CSS styles into our app:

@import 'bootstrap';

Now if you stop, re-run your Rails server and refresh the page you should see the same thing, but with subtle changes in the font and layout:

Default page with Twitter Bootstrap styles

This may not look much different, but actually there are subtle changes in the fonts, and also the text is flush against the top left corner now. These changes mean we have successfully loaded Twitter Bootstrap into our Rails app! If you ran View –> Source in your browser and inspected the code returned by the origami_hub.css request, you’d see all of the Twitter styles.

Step 3: Add Scaffolding

So far, so good; now we have our site’s navigation bar appearing correctly. As a next step, let’s create an Origami model along with pages for displaying and editing them – Rails scaffolding will be perfect. For today, I’ll just use two string attributes; the name of the origami artwork and the name of the artist. Here are the commands:

$ rails generate scaffold origami name:string artist:string
$ rake db:migrate
$ rm app/assets/stylesheets/scaffolds.css.scss
$ rm app/assets/stylesheets/origamis.css.scss

Notice that I deleted two generated files called “scaffolds.css.scss” and “origamis.css.scss” which interfere with Twitter Bootstrap’s styles. Now if you open the origami index page, http://localhost:3000/origamis, you’ll see this:

Index page from Rails scaffold generatorwith Twitter Bootstrap styles

This should look familiar if you’ve ever used Rails scaffolding before, but here we also see the Twitter Bootstrap table styling.

Step 4: Add Formtastic using Formtastic-Bootstrap

Our next step today will be to introduce Formtastic, written by Justin French, into our sample app. If you’re not familiar with it yet, Formtastic produces cleaner HTML than the standard Rails “form_for” and related methods, making it easier to create a nice looking form. It’s also easier to use while writing Rails view code. Finally, Formtastic’s HTML is also easier to work with while writing Javascript code or Cucumber tests, since there are CSS styles added to make finding specific form elements easier.

Unfortunately, Formtastic and Twitter Bootstrap don’t play well together: Twitter’s styles don’t refer to the HTML tags produced by Formtastic. But we can get these two components to work together by using a great new gem called Formtastic-Bootstrap, by Matthew Bellantoni – a Boston Rubyist like me. Take a look at the github readme page for more details on how Formtastic-Bootstrap actually works.

To put it into our application, I need to first add it to my Gemfile:

gem 'formtastic-bootstrap'

And now as Matthew explains on his readme page, I also need to create a new file called config/initializers/formtastic.rb, which should contain this one line of code:

Formtastic::Helpers::FormHelper.builder = FormtasticBootstrap::FormBuilder

This instructs Formtastic to use Matthew’s new form builder object, instead of Formtastic’s standard form builder. Matthew’s form builder is what generates the HTML Twitter expects.

Next, I need to rewrite the form produced by the Rails scaffold generator to use Formtastic’s semantic_form_for function – paste this code into app/views/origamis/_form.html.erb, overwriting what was there before:

<%= semantic_form_for @origami do |f| %>
  <%= f.semantic_errors %>
  <%= f.inputs do %>
    <%= f.input :name,   :hint => "Enter the origami artwork's name" %>
    <%= f.input :artist, :hint => "Enter the origami artist's name" %>
  <% end %>
  <%= f.buttons do %>
    <%= f.commit_button :button_html => {:class => "primary"} %>
  <% end %>
<% end %>

A couple of details to note here:

  • I’ve passed in the Formtastic “hint” option for each of my fields to add some help text on the screen, and
  • I’ve passed in the “button_html” option to use the Twitter Bootstrap blue button style

We need to run bundle install again to install Matthew’s gem; bundler will also install Formtastic itself since it’s a dependency for Formtastic-Bootstrap:

$ bundle install

After restarting the server and clicking on the “New Origami” link I get a nice looking form that uses the Twitter Bootstrap styles:

Form rendered by FormtasticBootstrap::FormBuilder

Step 5: Adding tab navigation with Tabulous

Another one of the great features of Twitter Bootstrap is the nice looking black navigation bar along the top of the page. How can we get that into our sample app? We could just copy/paste the HTML code in from one of the Twitter examples pages, but instead I’ll show you how to use a great new gem called Tabulous. Wyatt Greene, another fellow Boston Rubyist, wrote Tabulous earlier this year and it’s tremendously easy to use. We’re lucky to have such a creative Ruby community here: two of the four gems I’m using today with Twitter Bootstrap were written in Boston! For more information on Tabulous, be sure to read two great articles Wyatt wrote when he introduced the gem in March: Introducing Tabulous: Tabs in Rails and Tutorial for Adding Tabs to Rails Using Tabulous.

Once again, let’s first add the gem to our app by editing the Gemfile:

gem 'tabulous'

…and running bundle install:

$ bundle install

Now as Wyatt explains in his tutorial, we need to run this command:

$ rails generate tabs

This will create a new file called app/tabs/tabulous.rb, where we declare all of the tabs we want to display in our site. I won’t explain all of the syntax here; again refer to Wyatt’s tutorial for more information on exactly what’s in tabulous.rb.

For our sample app, we’ll just need to make a minor edit to the tabs table:

config.tabs do
[
  [ :welcome_tab,  'Welcome',  root_path,     true, true ],
  [ :origamis_tab, 'Origamis', origamis_path, true, true ],
]
end

It’s amazing how Wyatt’s generator already did most of the work for us! All I did here was reorder the two lines. For the sake of readability and to save space I removed some comments that normally appear in the tabulous.rb file explaining the purpose of each column in the table; you’ll see those if you open the tabulous.rb file on your machine.

And we’re almost done! The last thing I need to do is add the HTML for displaying the Twitter Bootstrap navigation bar. To do that, I’ll just copy/paste some HTML from their “fluid.html” example page – you can find this HTML in the Twitter Bootstrap github repo. The HTML should go into the app/views/layouts/application.html.erb file, between the <body> tag and the call to yield:

<body>

<div class="topbar">
  <div class="topbar-inner">
    <div class="container-fluid">
      <a class="brand" href="#">OrigamiHub</a>
      <%= tabs %>
    </div>
  </div>
</div>

<%= yield %>

Notice I replaced the <ul>… </ul> HTML from Twitter’s example with a single call to <%= tabs %>. This will display the tabs that I’ve declared in the tab table above!

Now restarting my server again – remember I ran bundle install earlier – let’s refresh the page:

Twitter Bootstrap navigation bar displayedwith Tabulous scaffold styles

Almost there… but this is still not quite right. By default, Tabulous will include some scaffolding tab CSS code to help you get started. However, since we’re using Twitter Bootstrap we don’t need any of that. To remove it, all we need to do is change the “scaffolding” setting to false in app/tabs/tabulous.rb:

config.css.scaffolding = false

We also need to change the “active_tab_clickable” setting to be true – this will tell Tabulous to always generate an <a> tag for each tab, which is what Twitter Bootstrap expects:

config.active_tab_clickable = true

Now let’s refresh our page once more:

Tabulous tabs in Twitter Bootstrap navigation barbut missing body padding style

And it works! Now we see the tabs appear properly, and not only that, they actually work too! You can click on “Welcome” to see the Welcome index placeholder page from above, and on “Origamis” to get the Origami index page, since we entered those paths into the tab table in app/tabs/tabulous.rb.

There’s one other CSS bug here you may not have noticed: the “New Origami” text at the top of the form was obscured by the navigation bar – this is because the way Twitter’s CSS code works is that it assumes the HTML body will have padding on it. To fix this, we just need to manually add the 60px padding on the body style in our origami_hub.css.scss file like this – be sure to put the padding style after the import or it won’t work:

@import 'bootstrap';

body {
  padding-top: 60px;
}

And refreshing the page once again we get:

Tabulous tabs in Twitter Bootstrap navigation barwith proper body padding

Wyatt’s Tabulous gem will also automatically display the currently active tab properly, since Tabulous and Twitter Bootstrap both use the “active” CSS style to indicate that. It all just works! Now as I add more pages to my app, I just need to add entries in the tabs table, and I’m also free to re-order them.

Conclusion

Twitter Bootstrap is a fantastic way to build a nice looking web site very quickly; however, having a sophisticated CSS library will only take you so far. You still need to build a web application of some kind to bring the Twitter design elements to life. Using Rails on the back end can be a perfect complement to Twitter Bootstrap, but, as we’ve seen today, using Rails can also be a challenge since the two frameworks weren’t designed to work together perfectly. Before you dive into building your next Rails 3.1 application with Twitter Bootstrap, be sure to do your homework – there are a lot of gem authors actively working in this area and as Twitter Bootstrap becomes more and more popular expect to see even more new gems and changes to existing gems.

Twitter Bootstrap and Rails

<< Twitter Bootstrap, Less, and Sass: Understanding Your Options for Rails 3.1How to Customize Twitter Bootstrap’s Design in a Rails app >>

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • Gady

    Excellent work!
    Can’t wait for the next twitter bootstrap articles !

  • http://alextambellini.com Alex

    and if you are a simple_form fan then you can use: https://github.com/rafaelfranca/simple_form-bootstrap

    • http://patshaughnessy.net Pat Shaughnessy

      Thanks for the link, Alex! I’ll have to try that one out…

  • http://www.watchmemo.com Todor Grudev

    pretty usefull thank you :)

  • Antonio

    Hey, thanks for the great article.

    I had to change the tabs table to root_path instead of welcome_index_path though.

    Antonio

    • http://patshaughnessy.net Pat Shaughnessy

      Yes, you’re right welcome_index_path does not work. Earlier I had a different routes.rb file and forget to update that in the tabs table.

      Article corrected now… Thanks a lot, Antonio!

  • http://leafac.com Leandro Facchinetti

    Great article, Pat!

    I found myself using bootstrap with rails before, but wasn’t aware of all these neat tricks about integration with other gems that generate html.

    I must warn that the last image, the one that shows the final product of the tutorial, is broken! There’s nothing at http://cdn.rubysource.com/files/2011/12/working-tabs-fixed.png.

    • http://patshaughnessy.net Pat Shaughnessy

      Thanks Leandro! We’ve fixed the image; let me know if you still have trouble seeing it.

  • http://www.yangzhiping.com ouyang

    Thanks!

    gem bootstrap_helper :

    https://github.com/xdite/bootstrap_helper

  • Anand

    Pat, I followed your instructions and things worked great, the only thing I am perplexed is why my form input area height is almost half as that as what you have on the example in this article. Not sure how to go about fixing this.

    Thank you

    • Anand

      My application.html.erb had , as per some other posts changing it to fixed this. Hope this help somebody.

      • Anand

        I changed my application.html.erb from “” to “” and this fixed the form input height problem.

  • Antonio

    Hey Pat,

    This works great in Rails 3.2 too :)

  • http://techiferous.com Wyatt Greene

    I just released version 1.2.0 of the tabulous gem which now supports Twitter Bootstrap version 2. See the gem’s README file for details on how to use with Twitter Bootstrap.

  • Pavel Varela

    With rails -v 3.2.1 i all ends up completely messed up :(

  • http://brightworks.me/ Ben Matthews

    For those using Rails 3.2 and Twitter Bootstrap 2.0, Sam Pointer has published a great tutorial on updating the gems and code to make this example app work:

    http://blog.sam-pointer.com/2012/02/12/formtastic-bootstrap-with-rails-3-2-and-twitter-bootstrap-2

    • http://patshaughnessy.net Pat Shaughnessy

      I just saw this myself – thanks Sam! Your update will be really helpful for people, since I wrote my articles at the worst possible time: just before Rails 3.2 and TB 2.0 were released, lol.

      • http://www.sam-pointer.com Sam Pointer

        Hey Pat,

        My pleasure – thanks for a great series. At the pace this stuff moves the window of “right time” is greatly diminishing. However, this is a very nice problem to have in some respects!

        Thanks Ben for posting the reference to my post; I’ve extended the comment period on it.

  • dreamrise

    Twitter Bootstrap 2.0

    ======app/tabs/tabulous.rb======

    config.css.scaffolding = false
    config.tabs_ul_class = “nav nav-pills” # or whatever Bootstrap class you want
    config.bootstrap_style_subtabs = true
    config.active_tab_clickable = true

    ======app/views/layouts/application.html.erb======

    OrigamiHub
    “all” %>


    Project name

    Logged in as username

  • dreamrise

    ======app/views/layouts/application.html.erb======
    ===========REPLACE [] TO ===========
    [!DOCTYPE html]

    [head]
      [title]OrigamiHub[/title]
      [%= stylesheet_link_tag    &quot;application&quot;, :media =] &quot;all&quot; %]
      [%= javascript_include_tag &quot;application&quot; %]
      [%= csrf_meta_tags %]
    [/head]
    [body]
    
    
        [div class=&quot;navbar navbar-fixed-top&quot;]
          [div class=&quot;navbar-inner&quot;]
            [div class=&quot;container-fluid&quot;]
              [a class=&quot;btn btn-navbar&quot; data-toggle=&quot;collapse&quot; data-target=&quot;.nav-collapse&quot;]
                [span class=&quot;icon-bar&quot;][/span]
                [span class=&quot;icon-bar&quot;][/span]
                [span class=&quot;icon-bar&quot;][/span]
              [/a]
              [a class=&quot;brand&quot; href=&quot;#&quot;]Project name[/a]
              [div class=&quot;nav-collapse&quot;]
    [%= tabs %]
                [p class=&quot;navbar-text pull-right&quot;]Logged in as [a href=&quot;#&quot;]username[/a][/p]
              [/div][!--/.nav-collapse --]
            [/div]
          [/div]
        [/div]
    
    
    
    
    [%= yield %]
    [/body]
    
  • http://kerspoon.com James Brooks

    Some things were missing for me: (helped by reading these)

    https://github.com/justinfrench/formtastic
    https://github.com/mjbellantoni/formtastic-bootstrap

    $ rails generate formtastic:install

    # app/assets/stylesheets/application.css
    *= require formtastic
    *= require formtastic-bootstrap

  • codinatrix

    Awesome tutorial! Thank you very much for this.

  • http://www.dynamick.it Mick

    Guys, look at http://openlastminute.it
    It’s a Bootstrap website with a masonry layout.
    It’s powered by rails 3.2.

  • Roman

    Why are you call scss as sass? Mb this is bootstrap-scss, not a sass?

  • hao

    Good post.

    step 3 rails generate scaffold origami name:string artist:string

    can be done by,
    rails generate scaffold origami name:string artist:string –skip-stylesheets

    then we don’t need to rm generated css files manually.