Using Bootstrap 3 and Simple Form in Rails 4, Upgrading from Bootstrap 2 to 3

Bootstrap 3 was released not so long ago. As I always like to be up-to-date with software to use the newest features I had to use it in my current Rails 4 project.

When I started the Rails 4 app I used some tutorial(s) from the internet to integrate bootstrap. They proposed to use Simple Form as well and so I did. I didn’t realize until a few days ago that I was using the old Bootstrap 2. So this is what I had to do to upgrade to Bootstrap 3:

Gemfile
Note, that I am using SASS and HAML.
Luckily, the official bootstrap-sass gem already integrated support for Bootstrap 3, it is not yet released to rubygems, hoever. So the github path needs to be added:

gem 'bootstrap-sass', github: 'thomas-mcdonald/bootstrap-sass'
# you should have this line already, of course your required version might differ. I believe it has to be > 3.2 though to work.
gem 'sass-rails',   '>= 3.2.3'

CSS
The new Glyphicons have to be added and bootstrap-responsive is not needed anymore.

# my bootstrap_and_overrides.css.scss
@import "bootstrap";
@import "bootstrap/glyphicons";
body { padding-top: 60px; }

Now, in Bootstrap 3 a few css classes changed their name. I will try to list the ones I was affected by:

/* button sizes were renamed */
.btn-small -> .btn-sm

/* the default button class does not have any style now, instead the btn-default class has to be added */
.btn -> .btn.btn-default

/* form stuff, which is shown in the next section */

/* a lot of the containers... */

Also, the icons changed. Alot. So I won’t bother listing that here but have a look at the documentation.

Simple Form
Unfortunately, the official repo does not yet support Bootstrap 3 yet, but it is quite easy to make it somehow work (for my limiting use). All that is needed is changes to the simple form initializer:

# config/initializers/simple_form_bootstrap.rb changes

# change the class name
-  config.wrappers :bootstrap, :tag => 'div', :class => 'control-group', :error_class => 'error' do |b|
+  config.wrappers :bootstrap, :tag => 'div', :class => 'form-group', :error_class => 'error' do |b|

# remove the wrapper around the control
-    b.wrapper :tag => 'div', :class => 'controls' do |ba|
-      ba.use :input
-      ba.use :error, :wrap_with => { :tag => 'span', :class => 'help-inline' }
-      ba.use :hint,  :wrap_with => { :tag => 'p', :class => 'help-block' }
-    end
+      b.use :input
+      b.use :error, :wrap_with => { :tag => 'span', :class => 'help-inline' }
+      b.use :hint,  :wrap_with => { :tag => 'p', :class => 'help-block' }

# add the new class name for controls
+  config.input_class = "form-control"
# config/initializers/simple_form_bootstrap.rb full
# Use this setup block to configure all options available in SimpleForm.
SimpleForm.setup do |config|
  config.wrappers :bootstrap, :tag => 'div', :class => 'form-group', :error_class => 'error' do |b|
    b.use :html5
    b.use :placeholder
    b.use :label
    #b.wrapper :tag => 'div', :class => 'controls' do |ba|
      b.use :input
      b.use :error, :wrap_with => { :tag => 'span', :class => 'help-inline' }
      b.use :hint,  :wrap_with => { :tag => 'p', :class => 'help-block' }
    #end
  end

  config.wrappers :prepend, :tag => 'div', :class => "control-group", :error_class => 'error' do |b|
    b.use :html5
    b.use :placeholder
    b.use :label
    b.wrapper :tag => 'div', :class => 'controls' do |input|
      input.wrapper :tag => 'div', :class => 'input-prepend' do |prepend|
        prepend.use :input
      end
      input.use :hint,  :wrap_with => { :tag => 'span', :class => 'help-block' }
      input.use :error, :wrap_with => { :tag => 'span', :class => 'help-inline' }
    end
  end

  config.wrappers :append, :tag => 'div', :class => "control-group", :error_class => 'error' do |b|
    b.use :html5
    b.use :placeholder
    b.use :label
    b.wrapper :tag => 'div', :class => 'controls' do |input|
      input.wrapper :tag => 'div', :class => 'input-append' do |append|
        append.use :input
      end
      input.use :hint,  :wrap_with => { :tag => 'span', :class => 'help-block' }
      input.use :error, :wrap_with => { :tag => 'span', :class => 'help-inline' }
    end
  end

  # Wrappers for forms and inputs using the Twitter Bootstrap toolkit.
  # Check the Bootstrap docs (http://twitter.github.com/bootstrap)
  # to learn about the different styles for forms and inputs,
  # buttons and other elements.
  config.default_wrapper = :bootstrap

  config.input_class = "form-control"
end

Haml
For the record, this is what my layout looks like

/ application.html.haml
!!!
%html
  %head
    %meta{:charset => "utf-8"}
    %meta{:name => "viewport", :content => "width=device-width, initial-scale=1, maximum-scale=1"}
    %title= content_for?(:title) ? yield(:title) : "AppTitle"
    %meta{:content => "", :name => "description"}
    %meta{:content => "", :name => "author"}
    = stylesheet_link_tag "application", :media => "all"
    = javascript_include_tag "application"
    = csrf_meta_tags
    = yield(:head)
  %body
    %header.navbar.navbar-inverse.navbar-fixed-top
      %nav.container
        = render 'layouts/navigation'
    #main{:role => "main"}
      .container
        .content
          .row
            .span12
              = render 'layouts/messages'
              = yield
          %footer
/ _navigation.html.haml
.navbar-header
  %button.navbar-toggle{type: "button", 'data-toggle' => "collapse", 'data-target' => ".navbar-collapse"}
    %span.icon-bar
    %span.icon-bar
    %span.icon-bar
  = link_to "AppTitle", root_path, :class => 'navbar-brand'
.navbar-collapse.collapse
  %ul.nav.navbar-nav
    %li
      = link_to "Home", root_path
/ etc

I won’t print my _messages.html.haml here because I have done big changes to that stuff and would probably only confuse some people. Also, there wasn’t any changes. If you are still curious have a look at my GitHub-Project.