Using Bootstrap with Webpacker in Rails

Build Blog with Ruby on Rails (Part 3)
Luan Nguyen
Luan Nguyen
Aug 30, 2020 · 5 min read

Source: unsplash.com/@anniespratt


This is part 3 in Project: Build Blog with Ruby on Rails

What'll we do:

  • What is the Asset Pipeline?
  • What is Webpack and Webpacker?
  • Introduction to Bootstrap
  • Installing Bootstrap with Webpacker in Blog application
  • Using Bootstrap to make up UI for Blog:
    • Layout of application
    • UI for CRUD Post
    • UI for Homepage

What is the Asset Pipeline?

The asset pipeline is a module which to process CSS, JavaScripts, and images which prepared for use by the browser. These processes include: concatenate, minify or compress assets, as well as pre-process assets that are written in other languages such as CoffeeScript, Sass, and ERB.
The asset pipeline is implemented by the sprockets-rails gem, and is enabled by default.

You can see that in layouts/application.html.erb
# Using Asset Pipeline by stylesheet_link_tag helper
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>


What is Webpack and Webpacker?

Webpack:
Webpack is a module bundler, used for managing and bundling JavaScript code.

Webpacker:
Webpacker is a gem that provides integration with Webpack module bundler and Yarn package manager.
It coexists with the Asset Pipeline, as the primary purpose for webpack is app-like JavaScript, not images, CSS, or even JavaScript Sprinkles (that all continues to live in app/assets).

In Rails 6, Webpacker is the default JavaScript compiler. It means that all the JavaScript code will be handled by Webpacker instead of through assets pipeline.
You can see that in layouts/application.html.erb
# Webpacker: Using javascript_pack_tag helper
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>


Introduction to Bootstrap

Bootstrap is the most popular front-end component library, which helps we build responsive, mobile-first projects on the web. 
It helps we quickly prototype your ideas or build your entire app with our Sass variables and mixins, responsive grid system, extensive prebuilt components, and powerful plugins built on jQuery.

Installing Bootstrap with Webpacker

Step 1: Install Bootstrap through yarn
yarn add bootstrap

Step 2: Install Bootstrap dependencies are: jQuery and popper.js
yarn add jquery popper.js

You can check in the package.json file:
{
  "dependencies": {
    [...]
    "bootstrap": "^4.5.2",
    "jquery": "^3.5.1",
    "popper.js": "^1.16.1",
    [...]
  },
}

Step 3: Import Bootstrap JavaScript and dependencies to Webpacker
# app/javascript/packs/application.js
import "jquery";
import "popper.js";
import "bootstrap";

Step 4: Import Bootstrap CSS to application.css (app/assets/stylesheets/application.css)
  • Rename application.css to application.scss
  • Then, remove all the *= require and *= require_tree statements from the Sass file. Instead, use @import to import Sass files.
  • Import Bootstrap styles to application.scss:
# In app/assets/stylesheets/application.scss
@import "../node_modules/bootstrap/scss/bootstrap";

Layout of Application

I’m going to structure our layout application to 3 main parts:
  • Header (navigation bar)
  • Main content
  • Footer
Layout.png 132 KB

Rails use default layout file: app/views/layouts/application.html.erb.
Add HTML code and using Bootstrap CSS for layout:
Header: Add navigation bar
# app/views/layouts/application.html.erb
<body>
  <!--Header-->
  <header>
    <nav class="navbar bg-dark">
      <div class="container">
        <a class="navbar-brand" href="<%= root_path %>">
          <%= image_tag 'logo.svg' %>
          <strong class="name">Blog</strong>
        </a>
      </div>
    </nav>
  </header>
  [...]
</body>

Main content:
# app/views/layouts/application.html.erb
<body>
  [...]
  <!--Main content-->
  <main class="container">
    <%= yield %>
  </main>
  [...]
</body>

Footer:
# app/views/layouts/application.html.erb
<body>
  [...]
  <!--Footer-->
  <footer class="p-4 bg-light">
    <div class="container text-muted">
      <p> 2020 @ Blog </p>
      <p class="float-right"> <a href="#">Back to top</a> </p>
      <p>
        Visit the
        <a href="https://fullstackrubyonrails.com"> FullstackRubyonRails</a>
        to learn more!
      </p>
    </div>
  </footer>
</body>


Update UI for CRUD Post

New/Edit Post Page

New/Create Post Page


Edit/Update Post Page


Using .form-group and .form-control class for New/Edit form as code below:
# In views/posts/_form.html.erb
<%= form_with(model: post, local: true) do |form| %>
  [...]
  <div class="form-group">
    <%= form.label :title %>
    <%= form.text_field :title, class: 'form-control' %>
  </div>

  <div class="form-group">
    <%= form.label :content %>
    <%= form.text_area :content, class: 'form-control' %>
  </div>

  <div class="actions">
    <button type="submit" class="btn btn-primary">Save</button>
  </div>
<% end %>

Post Index Page

Post Index page


Add .table and .table-hover class to to make up the Post table:
# In views/posts/index.html.erb
<table class="table table-hover">
  [...]
</table>


UI for Homepage

Homepage

We're going to show all posts to Home page like above image.
Hello, world! section:
<div class="jumbotron text-center bg-white">
  <h1>Hello, world!</h1>
  <p class="lead">Guide you step by step learning Ruby on Rails 
through building a Blog application.</p>
  <br>
  <a class="btn btn-primary btn-lg" href="https://fullstackrubyonrails.com" 
role="button" target="_blank">Learn more</a>
</div>

Show all posts section:
In HomeController, add @posts variable which contain all ordered posts to index action.
class HomeController < ApplicationController
  def index
    @posts = Post.order(created_at: :desc)
  end
end

All posts which ordered by created_at field.
@posts = Post.order(created_at: :desc)

We display posts in homepage view: app/views/home/index.html.erb
<div class="posts pb-md-4">
  <div class="container">
    <div class="row">
      <% @posts.each do |post| %>
        <section class="col-md-4">
          <!-- post view -->
        </section>
      <% end %>
    </div>
  </div>
</div>

Each Post view: 
<section class="col-md-4">
  <!-- post view -->
  <div class="card mb-4">
    <div class="card-body">
      <h5 class="card-title"> 
        <%= post.title %> 
      </h5>
      <p class="card-text">
        <%= post.content.truncate(100) %>
      </p>
      <a href="#" class="btn btn-primary">View details</a>
    </div>
  </div>
</section>

Add Manage Posts to Header
Header
<header>
  <nav class="navbar bg-dark">
    [...]
    <ul class="navbar-nav mr-auto mt-2 mt-lg-0">
      <li class="nav-item active">
        <%= link_to 'Manage Posts', posts_path, class: "nav-link" %>
      </li>
    </ul>
  </nav>
</header>

Conclusion

In this article, I guide you step by step install and using Bootstrap for Homepage and CRUD Post in Blog application.
In the next article, I'll going to share about how to use Active Storage component to upload Photos for Post.