Upgrade Rails 6 to Rails 7 and install Bootstrap v5
Published: 2022-05-02 06:00:59

Let's first upgrade Rails to v7

## Upgrade Rails to v7
```
// In Gemfile

gem 'rails', '~> 7.0.0' # Change to this
```

```
// In the terminal

$ bundle update
```

## Upgrade rails packages
In `package.json`, update all rails packages
```
$ yarn upgrade @rails/actioncable --latest
$ yarn upgrade @rails/activestorage --latest
$ yarn upgrade @rails/ujs --latest
$ yarn upgrade @rails/webpacker --latest
```

## Run update rails task
```
// In terminal

$ bin/rails app:update
```

## Verify framework defaults
```
// In config/application.rb

# old
config.load_defaults 6.1 # Change to 7.0

# new
config.load_defaults 7.0 # After change to 7.0
```

If you encountered this error
```
PG::UndefinedTable: ERROR: relation "active_storage_blobs" does not exist
```
Then do the following:
```
// In terminal

$ rails active_storage:install
```
It will create a `create_active_storage_tables.active_storage.rb` file in `db/migrate`, then
```
// In terminal

$ rails db:migrate
```
Then, go back to Verify framework defaults section, and proceed.
Read this [stackoverflow solution](https://stackoverflow.com/questions/59857774/pgundefinedtable-error-relation-active-storage-blobs-does-not-exist)

---
Now, we will proceed to install bootstrap v5.

## Install `bootstrap` and `popperjs/core` to dependencies
```
// In terminal

$ yarn add bootstrap and popperjs/core
```

So, your `package.json` file should have these 2 lines added:
```
"dependencies": {
    "@popperjs/core": "^2.11.5",
    "bootstrap": "^5.1.3"
}
```
Note: The versions here might be different but since our purpose is to install bootstrap v5, it must be something similar to `5.x.x`.

## Change `extract_css` in `default` to `true`
```
// In config/webpacker.yml

default: &default
  extract_css: true # Change to true
```

## Change `stylesheet_link_tag` to `stylesheet_pack_tag`
Since the original app is still with config of Rails v6, we would use Webpacker instead of Sprockets/Asset Pipeline
```
// In app/views/layouts/<filename>.html.erb
// My <filename> is application, so in app/views/layouts/application.html.erb

<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> # Change this
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
```

Then, it should look like this:
```
<%= stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> # After changing
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
```
Note: The 'application' is your `<filename>`

## Import bootstrap in `app/javascript`
In `app/javascript` create a folder `stylesheets` and create `application.scss` in the `stylesheets` folder
```
// The file structure should look like this
// Note application.scss can be changed to <filename.scss>
app
 |_ javascript
     |_ stylesheets
         |_ application.scss
```

Then, import the bootstrap in the file
```
// In app/javascript/stylesheets/application.scss

@import "bootstrap"
```

Then, put the following code in the bottom of the `app/javascript/packs/application.js` file
```
// In app/javascript/packs/application.js

import "bootstrap"
import "../stylesheets/application"

// Remember to change it to <filename>
```

## Now, let's do testing
In `app/views/layouts/application.html.erb`, put the following code in your `<body>` tag and before the `<%= yield %>` tag.
```
<body>
    <nav class="navbar navbar-expand-lg navbar-light bg-light">
      <div class="container-fluid">
        <a class="navbar-brand" href="#">Navbar</a>
        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
          <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarSupportedContent">
          <ul class="navbar-nav me-auto mb-2 mb-lg-0">
            <li class="nav-item">
              <a class="nav-link active" aria-current="page" href="#">Home</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#">Link</a>
            </li>
            <li class="nav-item dropdown">
              <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
                Dropdown
              </a>
              <ul class="dropdown-menu" aria-labelledby="navbarDropdown">
                <li><a class="dropdown-item" href="#">Action</a></li>
                <li><a class="dropdown-item" href="#">Another action</a></li>
                <li><hr class="dropdown-divider"></li>
                <li><a class="dropdown-item" href="#">Something else here</a></li>
              </ul>
            </li>
            <li class="nav-item">
              <a class="nav-link disabled">Disabled</a>
            </li>
          </ul>
          <form class="d-flex">
            <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
            <button class="btn btn-outline-success" type="submit">Search</button>
          </form>
        </div>
      </div>
    </nav>
    <%= yield %>
</body>
```

Check whether the navbar (dropdown etc) is working.

Cheers~ Happy Coding!
---