capybara cant find simple_form field with collection - ruby-on-rails

I have simple_form form with fields
<%= simple_form_for(#menu) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">enter code here
<%= f.input :order_date, :input_html => { :value => Time.now.strftime("%A") } %>
<%= f.input :title %>
<%= f.input :dish_category, input_html: {id: "dish_category"}, as: :radio_buttons, collection: ["First course", "Main course", "Drink"] %>
<%= f.input :description %>
<%= f.input :price %>
</div>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
And it works fine. But when I testing it with capybara, it gives me an error:
Failures:
1) Lunches Admin create menu lunches admin can create new menu only for today
Failure/Error: fill_in 'Dish category', :with => 'First course'
Capybara::ElementNotFound:
Unable to find field "Dish category"
Test itself:
scenario "lunches admin can create new menu only for today" do
admin = FactoryGirl.create(:lunches_admin)
login_as(admin)
visit new_menu_path
fill_in "Order date", :with => Time.now.strftime("%A")
fill_in "Title", :with => "Borsh"
fill_in "Description", :with => "Mmm, yamy"
fill_in "Price", :with => 99.99
fill_in 'Dish category', :wit`enter code here`h => 'First course'
click_button 'Create Menu'
expect(page).to have_content "Menu was successfully created."
end
The HTML itself: (I have to write something more, because the program says that it's to many code and not enough words)
<form novalidate="novalidate" class="simple_form new_menu" id="new_menu" action="/menus" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="✓" /><input type="hidden" name="authenticity_token" value="Dgh1T4kP0h/bqnXo6blYSu8lBPLwbM/3XD8sKVijc61YTYPmjVlwdHFfPZuaqwARambyChdOVstRQuO6WmgPbQ==" />
<div class="form-inputs">
<div class="form-group string optional menu_order_date"><label class="string optional control-label" for="menu_order_date">Order date</label><input value="Friday" class="string optional form-control" type="text" name="menu[order_date]" id="menu_order_date" /></div>
<div class="form-group string required menu_title"><label class="string required control-label" for="menu_title"><abbr title="required">*</abbr> Title</label><input class="string required form-control" type="text" name="menu[title]" id="menu_title" /></div>
<div class="form-group radio_buttons required menu_dish_category"><label class="radio_buttons required control-label" for="dish_category"><abbr title="required">*</abbr> Dish category</label><span class="radio"><label for="menu_dish_category_first_course"><input id="dish_category" class="radio_buttons required" type="radio" value="First course" name="menu[dish_category]" />First course</label></span><span class="radio"><label for="menu_dish_category_main_course"><input id="dish_category" class="radio_buttons required" type="radio" value="Main course" name="menu[dish_category]" />Main course</label></span><span class="radio"><label for="menu_dish_category_drink"><input id="dish_category" class="radio_buttons required" type="radio" value="Drink" name="menu[dish_category]" />Drink</label></span></div>
<div class="form-group text required menu_description"><label class="text required control-label" for="menu_description"><abbr title="required">*</abbr> Description</label><textarea class="text required form-control" name="menu[description]" id="menu_description">
</textarea></div>
<div class="form-group decimal required menu_price"><label class="decimal required control-label" for="menu_price"><abbr title="required">*</abbr> Price</label><input class="numeric decimal required form-control" type="number" step="any" name="menu[price]" id="menu_price" /></div>
</div>
<div class="form-actions">
<input type="submit" name="commit" value="Create Menu" class="btn btn-default" />
</div>
</form>

Since dish_category is a radio button, you need to use another capybara selector in order to interact with it.
Change
fill_in 'Dish category', :with => 'First course'
to:
choose('First course')
and that should do the trick.
You can read more about capybara selectors for forms here: https://github.com/jnicklas/capybara#interacting-with-forms

Related

Capybara Unable to find field

Hello I am doing my very first tests and I would need your help. I am using Rails5.
The problem is because of the nested fields I believe...(used Cocoon gem)
Capybara returns this error:
Capybara::ElementNotFound:
Unable to find field "event_participants_attributes_1489697584487_first_name"
my html looks like this:
<div class="nested-fields">
<div class="form-group string optional event_participants_first_name"><label class="control-label string optional" for="event_participants_attributes_1489697584487_first_name">Participant's first name</label><input class="form-control string optional" type="text" name="event[participants_attributes][1489697584487][first_name]" id="event_participants_attributes_1489697584487_first_name" data-com.agilebits.onepassword.user-edited="yes"></div>
<div class="form-group integer optional event_participants_salary"><label class="control-label integer optional" for="event_participants_attributes_1489697584487_salary">Participant's monthly pay</label><input class="form-control numeric integer optional" type="number" step="1" name="event[participants_attributes][1489697584487][salary]" id="event_participants_attributes_1489697584487_salary"></div>
<div class="links">
<input type="hidden" name="event[participants_attributes][1489697584487][_destroy]" id="event_participants_attributes_1489697584487__destroy" value="false"><a class="btn btn-danger btn-xs btn-remove-friend remove_fields dynamic" href="#">Remove this friend</a>
</div>
</div>
and here is my features/events/create_event.spec.rb
require 'spec_helper'
require 'rails_helper'
describe "Creating an event" do
it "redirects on result page on success" do
visit "/"
click_link "Create a new event"
expect(page).to have_content('Wanna share fair?')
fill_in :name, with: 'Rent a plane'
fill_in "What is the total price", with: 200
click_link "Add a participant"
fill_in "event_participants_attributes_1489697584487_first_name", with: "John"
enter code here
fill_in ":event_participants_attributes_1489697584487_salary", with: 2300
click_button "See result"
expect(page).to have_content('Your salary together:')
end
end
And here are my simple_forms:
_form.html.erb
<%= simple_form_for #event do |f| %>
<div class="col-xs-12 col-md-10 col-md-offset-1">
<h1>Wanna share fair?</h1>
<p>Create an event, enter the bill to share.</p>
<%= f.input :name, label: "Event's name" %>
<%= f.input :total_price, label: "What is the total price" %>
<p>Add the participants.</p>
<div id="participants">
<%= f.simple_fields_for :participants do |participant| %>
<%= render "participants_fields", f: participant %>
<% end %>
<div class="links text-center">
<%= link_to_add_association "Add a participant", f, :participants, partial: "participants_fields", class:"btn btn-primary btn-sm btn-add-friend" %>
</div>
</div>
</div>
<div class="col-xs-12 col-md-10 col-md-offset-1 text-center">
<%= f.submit "See result" , class:"btn btn-success btn-lg btn-event" %>
</div>
<% end %>
_participants_fields.html.erb
<div class="nested-fields">
<%= f.input :first_name, label: "Participant's first name" %>
<%= f.input :salary, label: "Participant's monthly pay" %>
<div class="links">
<%= link_to_remove_association "Remove this friend", f , class: "btn btn-danger btn-xs btn-remove-friend" %>
</div>
</div>
edit more html
<form novalidate="novalidate" class="simple_form new_event" id="new_event" action="/events" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="✓"><input type="hidden" name="authenticity_token" value="O5XM0JMiVBbpPNaKF1apw7rdtC/XEBhasZQoK6POycZQ2Zp14Td1ljoJyIUKTwtl91LlBHeDkKFtcWRnNu+iEQ==">
<div class="col-xs-12 col-md-10 col-md-offset-1">
<h1>Wanna share fair?</h1>
<p>Create an event, enter the bill to share.</p>
<div class="form-group string optional event_name"><label class="control-label string optional" for="event_name">Event's name</label><input class="form-control string optional" type="text" name="event[name]" id="event_name" data-com.agilebits.onepassword.user-edited="yes"></div>
<div class="form-group integer optional event_total_price"><label class="control-label integer optional" for="event_total_price">What is the total price</label><input class="form-control numeric integer optional" type="number" step="1" name="event[total_price]" id="event_total_price" data-com.agilebits.onepassword.user-edited="yes"></div>
<p>Add the participants.</p>
<div id="participants">
<div class="nested-fields">
<div class="form-group string optional event_participants_first_name"><label class="control-label string optional" for="event_participants_attributes_1489705438668_first_name">Participant's first name</label><input class="form-control string optional" type="text" name="event[participants_attributes][1489705438668][first_name]" id="event_participants_attributes_1489705438668_first_name" data-com.agilebits.onepassword.user-edited="yes"></div>
<div class="form-group integer optional event_participants_salary"><label class="control-label integer optional" for="event_participants_attributes_1489705438668_salary">Participant's monthly pay</label><input class="form-control numeric integer optional" type="number" step="1" name="event[participants_attributes][1489705438668][salary]" id="event_participants_attributes_1489705438668_salary" data-com.agilebits.onepassword.user-edited="yes"></div>
<div class="links">
<input type="hidden" name="event[participants_attributes][1489705438668][_destroy]" id="event_participants_attributes_1489705438668__destroy" value="false"><a class="btn btn-danger btn-xs btn-remove-friend remove_fields dynamic" href="#">Remove this friend</a>
</div>
</div><div class="nested-fields">
<div class="form-group string optional event_participants_first_name"><label class="control-label string optional" for="event_participants_attributes_1489705443842_first_name">Participant's first name</label><input class="form-control string optional" type="text" name="event[participants_attributes][1489705443842][first_name]" id="event_participants_attributes_1489705443842_first_name" data-com.agilebits.onepassword.user-edited="yes"></div>
<div class="form-group integer optional event_participants_salary"><label class="control-label integer optional" for="event_participants_attributes_1489705443842_salary">Participant's monthly pay</label><input class="form-control numeric integer optional" type="number" step="1" name="event[participants_attributes][1489705443842][salary]" id="event_participants_attributes_1489705443842_salary" data-com.agilebits.onepassword.user-edited="yes"></div>
<div class="links">
<input type="hidden" name="event[participants_attributes][1489705443842][_destroy]" id="event_participants_attributes_1489705443842__destroy" value="false"><a class="btn btn-danger btn-xs btn-remove-friend remove_fields dynamic" href="#">Remove this friend</a>
</div>
</div><div class="links text-center">
<a class="btn btn-primary btn-sm btn-add-friend add_fields" data-association="participant" data-associations="participants" data-association-insertion-template="<div class="nested-fields">
<div class="form-group string optional event_participants_first_name"><label class="control-label string optional" for="event_participants_attributes_new_participants_first_name">Participant&#39;s first name</label><input class="form-control string optional" type="text" name="event[participants_attributes][new_participants][first_name]" id="event_participants_attributes_new_participants_first_name" /></div>
<div class="form-group integer optional event_participants_salary"><label class="control-label integer optional" for="event_participants_attributes_new_participants_salary">Participant&#39;s monthly pay</label><input class="form-control numeric integer optional" type="number" step="1" name="event[participants_attributes][new_participants][salary]" id="event_participants_attributes_new_participants_salary" /></div>
<div class="links">
<input type="hidden" name="event[participants_attributes][new_participants][_destroy]" id="event_participants_attributes_new_participants__destroy" value="false" /><a class="btn btn-danger btn-xs btn-remove-friend remove_fields dynamic" href="#">Remove this friend</a>
</div>
</div>
" href="#">Add a participant</a>
</div>
</div>
</div>
<div class="col-xs-12 col-md-10 col-md-offset-1 text-center">
<input type="submit" name="commit" value="See result" class="btn btn-success btn-lg btn-event" data-disable-with="See result">
</div>
</form>
IIRC the "1489697584487" part of the ids you show is created by Cocoon based on the current timestamp. That means every time you run your test the number will be different so you're not going to be able to select those elements by id.
Instead if you're only adding one participant you should be able to do something like
fill_in "Participant's first name", with: "John"
fill_in "Participant's monthly pay", with: "2300"
If you are adding multiple participants then depending on the exact layout you can use nth-child/nth-of-type CSS selectors to scope the fill_in or use all and select the one you want, etc.
find('.nested-fields:nth-child(2)').fill_in ...
all(:field, "Participant's first name", minimum: 2)[1].set("John") # 0 based index so minimum should be 1 more than the index you want
Also - For any of this to work you need to be using a JS capable driver (Cocoon requires JS). You haven't tagged your spec with js: true metadata so either you've overridden the default driver, or you're not currently using a JS capable driver - see https://github.com/teamcapybara/capybara#selecting-the-driver. Also see https://github.com/teamcapybara/capybara#transactions-and-database-setup and https://github.com/DatabaseCleaner/database_cleaner#rspec-with-capybara-example if you haven't yet configure database_cleaner for use with JS capable drivers

rails is processing trash html codes

This is the rails form helper code,
<%= form_tag({ :action => "create"}, :method => "POST", :id=>"login") do -%>
<h1>Log In</h1>
<fieldset id="inputs">
<%= text_field :username, :placeholder => 'Username', :autofocus=>true%>
<%= password_field_tag :userpass, params[:userpass], placeholder: 'Password', id:'password'%>
</fieldset>
<fieldset id="actions">
<input type="submit" id="submit" value="Log in">
Register
</fieldset>
<% end %>
and this is the html code, what i want,
<form action="/login/create" method="post" id="login" >
<h1>LogIn</h1>
<fieldset id="inputs">
<input id="username" type="text" name ="username" placeholder="Username" autofocus required>
<input id="password" type="password" name="userpass" placeholder="Password" required>
</fieldset>
<fieldset id="actions">
<input type="submit" id="submit" value="Log in" name="apply">
Register
</fieldset>
</form>
However, if i run the rails code, it makes the code like this,
<input id="username_{:placeholder=>"Username", :autofocus=>true}" name="username[{:placeholder=>"Username", :autofocus=>true}]" size="30" type="text">
Somebody knows what the problem is?
You'll want to use text_field_tag in your form, not just text_field:
<%= form_tag({ :action => "create"}, :method => "POST", :id=>"login") do -%>
<h1>Log In</h1>
<fieldset id="inputs">
<%= text_field_tag :username, params[:username], { :placeholder => 'Username', :autofocus => true } %>
<%= password_field_tag :userpass, params[:userpass], placeholder: 'Password', id:'password'%>
</fieldset>
<fieldset id="actions">
<input type="submit" id="submit" value="Log in">
Register
</fieldset>
<% end %>
You should also look into field_set_tag - that may save you some headaches if you're expecting to use the HTML fieldset tag.

Inline Radio Buttons using simple form and twitter bootstrap

I am trying to create a form that displays the radio options inline like this:
O Apple O Microsoft O Twitter O Square
Currently I have this line:
<%= f.association :company, as: :radio, label: false %>
But my form looks like this:
O Apple
O Microsoft
O Twitter
O Square
I have tried <div class="form-inline"></div> around that input and also adding
<%= f.association :company, as: :radio, label: false, :item_wrapper_class => 'inline' %>
Do I need to change the input to collection?
with regular rails you can do
<div class="radio">
<label>
<%= radio_button_tag "Product Type", "Retail Product or Service", true %>
Retail Product or Service
</label>
<label>
<%= radio_button_tag "Product Type", "Tax Code", false %>
Tax Code
</label>
<label>
<%= radio_button_tag "Product Type", "Discount Amount", false %>
Discount Amount
</label>
<label>
<%= radio_button_tag "Product Type", "Discount Percent", false %>
Discount Percent
</label>
</div>
You can use this:
<label class="checkbox inline">
<input type="checkbox" id="inlineCheckbox1" value="option1"> 1
</label>
<label class="checkbox inline">
<input type="checkbox" id="inlineCheckbox2" value="option2"> 2
</label>
<label class="checkbox inline">
<input type="checkbox" id="inlineCheckbox3" value="option3"> 3
</label>
Or this one (tag form only):
<form class="form-inline">
<input type="text" class="input-small" placeholder="Email">
<input type="password" class="input-small" placeholder="Password">
<label class="checkbox">
<input type="checkbox"> Remember me
</label>
<button type="submit" class="btn">Sign in</button>
</form>

How do I create an interactive form with Simple Form?

I have a model (Listing) that has many, many attributes (say 25).
I would like to create an AJAX form that is dynamic based on the input in the form.
Meaning that if a user chooses type=b, they will see other fields that they should see and not ones they shouldn't.
Ideally they should load immediately, with the right content from the db - i.e. in an AJAXy way.
What's the best way to approach this?
Thanks.
Edit: Here is an example of my _form.html.erb. You will notice that I have included 2 if statements that indicate which fields should show if the property_type value chosen is one of those specified:
<%= simple_form_for(#listing) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :headline %>
<%= f.input :price %>
<%= f.association :property_type %>
If property_type == "coop"
<%= f.input :maintenance %>
<%= f.input :coop_deductible %>
<%= f.input :flip_tax %>
if property_type == "condo"
<%= f.input :common_charges %>
<%= f.input :taxes %>
</div>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
Edit 2:
This is the Rails form helper that I used - powered by the gem Simple_Form:
<%= simple_form_for #listing, :defaults => { :wrapper_html => { :class => 'form-horizontal' } } do |f| %>
<%= f.error_notification %>
<fieldset>
<%= f.association :listing_category, :label => "Category: ", :label_html => { :class => "control-label"}, :wrapper_html => { :class => "controls"} %>
<div style="display: none;" data-show-for="Exclusive">
<%= f.association :listing_type %>
<%= f.association :user %>
<%= f.association :boro %>
</div>
<div style="display: none;" data-show-for="Open">
<%= f.association :neighborhood %>
<%= f.association :building %>
<%= f.association :term %>
<%= f.association :property_type %>
</div>
<div class="form-actions">
<%= f.button :submit, :class => "btn btn-primary" %>
<!-- <button type="submit" class="btn btn-primary">Save and Continue</button>
<button type="reset" class="btn">Cancel</button> -->
</div>
</fieldset>
<% end %>
This is the HTML it produced:
<form accept-charset="UTF-8" action="/listings" class="simple_form new_listing" id="new_listing" method="post" novalidate="novalidate"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓" /><input name="authenticity_token" type="hidden" value="1oDfg41Wx/SiPCsvf4qTAcxhFUGSNlhlLfkMy8nHW1E=" /></div>
<fieldset>
<div class="control-group select optional controls"><label class="select optional control-label control-label" for="listing_listing_category_id">Category:</label><div class="controls"><select class="select optional" id="listing_listing_category_id" name="listing[listing_category_id]"><option value=""></option>
<option value="1">Exclusive</option>
<option value="2">Open</option></select></div></div>
<div style="display: none;" data-show-for="Exclusive">
<div class="control-group select optional form-horizontal"><label class="select optional control-label" for="listing_listing_type_id">Listing type</label><div class="controls"><select class="select optional" id="listing_listing_type_id" name="listing[listing_type_id]"><option value=""></option>
</select></div></div>
<div class="control-group select optional form-horizontal"><label class="select optional control-label" for="listing_user_id">User</label><div class="controls"><select class="select optional" id="listing_user_id" name="listing[user_id]"><option value=""></option>
<option value="1">First User</option>
<option value="2">Second User</option>
<option value="3">Third User</option>
<option value="4">Fourth User</option>
<option value="5">Fifth User</option></select></div></div>
<div class="control-group select optional form-horizontal"><label class="select optional control-label" for="listing_boro_id">Boro</label><div class="controls"><select class="select optional" id="listing_boro_id" name="listing[boro_id]"><option value=""></option>
<option value="1">Brooklyn</option></select></div></div>
</div>
<div style="display: none;" data-show-for="Open">
<div class="control-group select optional form-horizontal"><label class="select optional control-label" for="listing_neighborhood_id">Neighborhood</label><div class="controls"><select class="select optional" id="listing_neighborhood_id" name="listing[neighborhood_id]"><option value=""></option>
<option value="1">Prospect Heights</option></select></div></div>
<div class="control-group select optional form-horizontal"><label class="select optional control-label" for="listing_building_id">Building</label><div class="controls"><select class="select optional" id="listing_building_id" name="listing[building_id]"><option value=""></option>
<option value="1">Trump Towers</option></select></div></div>
<div class="control-group select optional form-horizontal"><label class="select optional control-label" for="listing_term_id">Term</label><div class="controls"><select class="select optional" id="listing_term_id" name="listing[term_id]"><option value=""></option>
</select></div></div>
<div class="control-group select optional form-horizontal"><label class="select optional control-label" for="listing_property_type_id">Property type</label><div class="controls"><select class="select optional" id="listing_property_type_id" name="listing[property_type_id]"><option value=""></option>
<option value="1">Coop</option></select></div></div>
</div>
<div class="form-actions">
<input class="btn btn btn-primary" name="commit" type="submit" value="Create Listing" />
<!-- <button type="submit" class="btn btn-primary">Save and Continue</button>
<button type="reset" class="btn">Cancel</button> -->
</div>
</fieldset>
</form>
This is the JS that I included in my listing.js - which corresponds to the file that this form is on app/views/listings/new.html.erb
$(document).ready(function({
$('#listing_listing_category_id').on('change', function(){
var option = $(this).find(':selected');
$('[data-show-for]').hide(); //And maybe reset?
$('[data-show-for="+ option.text +"]').show()
});
});
When I chose the option I want, it doesn't show me the fields I want to see.
Personally I wouldn't use AJAX, just straight JS/JQuery to show/hide on click using data attributes.
See fiddle: http://jsfiddle.net/XnPZF/
First, add the data attributes to the sections you want to hide/show:
<div style="display: none;" data-show-for="coop">
<%= f.input :maintenance %>
<%= f.input :coop_deductible %>
<%= f.input :flip_tax %>
</div>
<div style="display: none;" data-show-for="condo">
<%= f.input :common_charges %>
<%= f.input :taxes %>
</div>
Then create a change event on the select:
$('#listing_property_type').on('change', function(){
var option = $(this).find(':selected');
$('[data-show-for]').hide(); //And maybe reset?
$('[data-show-for='+ option.text() +']').show()
});
For data-show-for, you can use Option text or value, just be sure to make sure the event knows which. If you plan to use this a lot of times, you could generalize it, but that would mean building your options.

Twitter bootstrap rails simple form formatting

I'm trying to reformat the simple default devise login screen with twitter bootstrap simple form and I'm having major issues.
Here is my code:
<h2>Sign in</h2>
<%= simple_form_for(resource, :as => resource_name, :url => session_path(resource_name), :html => {:class => "form-horizontal"}) do |form| %>
<%= form.input :email, :autofocus => true %>
<%= form.input :password %>
<%= form.input :remember_me, :as => :boolean if devise_mapping.rememberable? %>
<%= form.button :submit, 'Sign in', :class => 'primary'%>
<% end %>
<%= render "links" %>
I can get the spacing between the labels and input fields to be correct if I add
.form-horizontal .controls {
margin-left: 160px;
}
to my application.css file, but I don't see this anywhere in their sample app here
https://github.com/rafaelfranca/simple_form-bootstrap
and am really confused where the proper formatting is coming from.
I have almost the same code as this guy https://github.com/rafaelfranca/simple_form-bootstrap/issues/6 but his code is older I think. I am using simple form 2.0.2 and I installed bootstrap with twitter-bootstrap-rails 1.4.3. I also installed and uninstalled a couple other twitter bootstrap gems if theres any chance that's messing things up.
Edit: here is my produced code if that helps
Sign in
<form accept-charset="UTF-8" action="/admins/sign_in" class="simple_form form-horizontal" id="new_admin" method="post" novalidate="novalidate"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓" /><input name="authenticity_token" type="hidden" value="xxx" /></div>
<div class="control-group email optional"><label class="email optional control-label" for="admin_email">Email</label><div class="controls"><input autofocus="autofocus" class="string email optional" id="admin_email" name="admin[email]" size="50" type="email" value="" /></div></div>
<div class="control-group password optional"><label class="password optional control-label" for="admin_password">Password</label><div class="controls"><input class="password optional" id="admin_password" name="admin[password]" size="50" type="password" /></div></div>
<div class="control-group boolean optional"><label class="boolean optional control-label" for="admin_remember_me">Remember me</label><div class="controls"><input name="admin[remember_me]" type="hidden" value="0" /><label class="checkbox"><input class="boolean optional" id="admin_remember_me" name="admin[remember_me]" type="checkbox" value="1" /></label></div></div>
<input class="btn primary" name="commit" type="submit" value="Sign in" />
</form>
Forgot your password?<br />
Wow that was painful. It turns out there is an error in the twitter-bootstrap-rails gem https://github.com/seyhunak/twitter-bootstrap-rails/issues/324
If you have this problem I recommend uninstalling that gem and everything associated with it and following these directions http://ruby.railstutorial.org/chapters/filling-in-the-layout?version=3.2#sec-custom_css
to get started. Summary of link:
Install 'bootstrap-sass' gem
Add a custom.css.scss file with "#import 'bootstrap';" and you're good to go.

Resources