Railsの基礎を使って、メッセージ投稿アプリを作ってみた　【第４章】（7.Bootstrapでスタイルをつける）

## 概要
前回の記事で作成したアプリの続きです。
[Railsの基礎を使って、メッセージ投稿アプリを作ってみた　【第3
章】　（6.エラーの処理）](https://qiita.com/web_fumiya/items/9c5dec049e6fa754fddb)

今回が最終章となります。
<font color="DeepPink">Bootstrap </font>と<font color="DeepPink"> FontAwesome </font>を導入し、簡単に見た目の良いサイトに仕上げていきます。

## 開発環境
- Ruby 2.7.3
- Rails 6.1.6.1
- Postgresql

## 開発手順
1.アプリの作成 (第１章)
2.CRUD処理で簡単なメッセージ投稿アプリを実装 (第１章)
3.リファクタリング （第２章）
4.フラッシュの実装 （第２章）
5.バリデーションの設定 （第２章）
6.エラーの処理 （第３章）
7.Bootstrapでスタイルをつける <font color="DeepPink">（第4章）</font>

## Bootstrap と FontAwesome の導入
<font color="DeepPink">Bootstrap </font>と<font color="DeepPink"> FontAwesome </font>を使用するには、
- ターミナルで<font color="DeepPink">Bootstrap </font>と<font color="DeepPink"> FontAwesome </font>をインストール
- 使用するファイルでインポート

まず、インストールから進めます。
```terminal:ターミナル
yarn add bootstrap@~4.5.1 jquery popper.js @fortawesome/fontawesome-free
```
次にファイルでインポートします。
```js:app/javascript/packs/application.js
// 略
import "bootstrap/dist/js/bootstrap"
import "@fortawesome/fontawesome-free/js/all"
```
```scss:app/assets/stylesheets/application.scss
// 略
@import "bootstrap/scss/bootstrap";

$fa-font-path: '@fortawesome/fontawesome-free/webfonts';
@import "@fortawesome/fontawesome-free/scss/fontawesome";
@import "@fortawesome/fontawesome-free/scss/regular";
// 略
```
これで、<font color="DeepPink">Bootstrap </font>と<font color="DeepPink"> FontAwesome </font>の導入できました。

Bootstrap や　FontAwesome の基本的な使い方に関しては、以下を参考にしてみてください。
参考：[Bootstrap ドキュメント](https://getbootstrap.jp/docs/5.0/getting-started/introduction/)
参考：[【Rails】 FontAwesomeの使い方](https://qiita.com/koki_73/items/fa6d31a3b54a84d19dcf)

### レスポンシブ対応
Bootstrapの最大のメリットと言われているのが、レスポンシブに対応しているところです。
レスポンシブに対応できることで、画面幅の違うPC、スマホ、タブレットなどの異なるサイズでも、最適なレイアウトを組むことができます。

レスポンシブ対応させるために、<font color="DeepPink">viewport </font>を追加します。
```erb:app/views/layouts/application.html.erb
<!-- 略 -->
<%= csp_meta_tag %>
<!-- 下記を追記 -->
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!--　略 -->
```

### ページ全体の最大横幅を設定し、中央寄せ
現状左寄せになっているので、全ページに対して中央寄せになるよう修正します。
```erb:app/views/layouts/application.html.erb
<!-- 略 -->
  <body>
    <header>
      <%= render "layouts/header" %>
    </header>
    <main>
      <%= render "layouts/flash" %>
      <div class="base-container">
        <%= yield %>
      </div>
    </main>
  </body>
</html>
```
`<%= render "layouts/header" %>`のヘッダー（リンク部分）は、後ほどナビバーにするので、ここでは`<%= yield %>`のみ<font color="DeepPink"> divタグ </font>で囲みます。
```scss:app/assets/stylesheets/application.scss
// 略
.base-containar {
  @extend .container-fluid;
  max-width: var(--breakpoint-lg);
  padding: 30px 15px;
}
```
指定した<font color="DeepPink">base-container</font>クラスに必要な属性を上記で記述します。
（var(--breakpoint-lg)は992pxです。）

### ヘッダーにナビバーを利用
今回は、本家のハンバーガーメニューのナビバーを使用します。
参考 : [Bootstrap Navbar](https://getbootstrap.jp/docs/4.5/components/navbar/)

```erb:app/views/layouts/_header.html.erb
<nav class="navbar navbar-expand-sm navbar-dark bg-primary fixed-top">
  <span class="navbar-brand">メッセージ投稿アプリ</span>
  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
    <span class="navbar-toggler-icon"></span>
  </button>
  <div class="collapse navbar-collapse" id="navbarNavAltMarkup">
    <div class="navbar-nav">
      <%= link_to "投稿一覧", posts_path, class: "nav-item nav-link active" %>
      <%= link_to "新規投稿", new_post_path, class: "nav-item nav-link active" %>
    </div>
  </div>
</nav>
```
変更した点は、
- 背景を`bg-primary`に変更
- <font color="DeepPink">navbar-expand-sm</font>とし、ハンバーガーメニューに切り替わる横幅を調整
- ナビバーが上部に固定されるよう<font color="DeepPink"> fixed-top </font>を追加

ここで、一度サーバーを起動し、スタイルが適用されているか、確認してみることをお勧めします。

確認してみると、ナビバーでページの上部が一部隠れてしまっているので、修正しておきます。
```scss:app/assets/stylesheets/application.scss
// 略
body {
  padding: 56px;
}
```

### 新規投稿でBootstrapのフォームを利用
<font color="DeepPink">form-group </font>, <font color="DeepPink">form-control </font>を追加し、フォームのスタイルを整えます。
参考：[Bootstrap Forms](https://getbootstrap.jp/docs/5.0/forms/overview/)
```erb:app/views/posts/_form.html.erb
<%= render "layouts/error_messages" %>
<%= 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._area :content, class: "form-control", rows: 10 %>
  </div>
  <div>
    <%= form.submit button_value, class: "btn btn-primary btn-block" %>
  </div>
<% end %>
```
変更点は、
- <font color="DeepPink">form-group</font>,<font color="DeepPink">form-control</font>を適切なところに追加
- 内容の投稿で改行できるように、<font color="DeepPink">text_field</font> を <font color="DeepPink">text_area</font>に変更。
- `rows: 10`で内容のフォームの縦幅を変更
- 投稿ボタンを`class: "btn btn-primary btn-block"`を指定し、ボタンの色を変更し横長にする。

### 詳細表示でBoorstrapのカードを利用
Bootstrapの<font color="DeepPink">カード</font>を使用し、実装します。
参考：[Bootstrap Cards](https://getbootstrap.jp/docs/5.0/components/card/)
```erb:app/views/posts/show.html.erb
<h1 class="text-center">投稿詳細</h1>
<section class="card border-dark mt-5">
  <div class="card-header">
    <h4><%= @post.title %></h4>
  </div>
  <div class="card-body">
    <p class="card-text"><%= simple_format(h @post.content) %></p>
  </div>
</section>
```
注意点は、`<%= simple_format(h @post.content) %>`に変更している点です。
先ほど、新規投稿フォームで、<font color="DeepPink">text_area</font>に変更し、改行できるようにしましたが、`<%= simple_format(h @post.content) %>`にすることで改行が反映されるようになります。

### 一覧表示でBootstrapのテーブルを利用
tableタグに<font color="DeepPink">table</font> クラスを指定することで、簡単にスタイルが出来上がります。
参考：[Bootstrap Tables](https://getbootstrap.jp/docs/5.0/content/tables/)
```erb:app/views/posts/index.html.erb
<h1 class="text-center">投稿一覧</h1>
<table class="table table-bordered table-striped mt-4">
  <thead>
    <tr>
      <th scope="col">No.</th>
      <th scope="col" class="w-100">タイトル</th>
      <th scope="col"></th>
    </tr>
  </thead>
  <tbody>
    <% @posts.each.with_index(1) do |post, i| %>
      <tr>
        <th scope="row" class="text-right"><%= i %></th>
        <td class="break-word"><%= post.title %></td>
        <td class="text-nowrap">
          <%= link_to post, class: "btn btn-primary" do %>
            <i class="fas fa-edit"></i> <span class="d-none d-md-inline"> 詳細</span>
          <% end %>
          <%= link_to edit_post_path(post), class: "btn btn-success" do %>
            <i class="far fa-edit"></i> <span class="d-none d-md-inline"> 編集</span>
          <% end %>
          <%= link_to post, method: :delete, data: { confirm: "削除しますか?" }, class: "btn btn-danger" do %>
            <i class="fa fa-trash-alt"></i> <span class="d-done d-md-inline"> 削除</span>
          <% end %>
        </td>
      </tr>
    <% end %>
  </tbody>
</table>
``` 
- `table-bordered`：　テーブルに枠をつける
- `table-striped`：　背景をストライブにする
- `w-100`：　タイトル部分を広くとるよう横幅を調整
- `text-nowrap`：　ボタンの文字が改行されないようにする
- `text-right`：　番号のみ右寄せ

ここで<font color="DeepPink"> FontAwesome </font>を使用し、アイコンも追加しています。
767px以下ではアイコンのみ、それ以上では文字も表示されるよう`d-none`,`d-md-inline`を追加し、レスポンシブに対応。

```scss:app/assets/stylesheets/application.scss
// 略

th,
td {
  vertical-align: middle !important;
}

.break-word {
  word-break: break-word;
}
```
`vertical-algin`を`middle`に設定し、上下中央寄せ
`word-break`を`break-word`に設定し、改行方法を指定

### フラッシュとエラーメッセージでBootstrapのアラートを利用
Bootstrapのアラートを利用することで、フラッシュやエラーメッセージの見やすくします。
参考：[Bootstrap Alerts](https://getbootstrap.jp/docs/5.0/components/alerts/)

まずは、フラッシュから
```erb:app/views/layouts/_flash.html.erb
<% flash.each do |flash_type, msg| %>
  <div class="alert alert-<%= flash_type %>" role="alert">
    <a href="#" class="close" data-dismiss="alert">×</a>
    <%= msg %>
  </div>
<% end %>
```
クラスを指定する際、`alert alert-<%= flash_type %>`とすることで、投稿に成功した場合は、`alert-notice`、失敗した場合は、`alert-alert`というクラスが指定されます。

しかし、`alert-notice`や`alert-alert`などのスタイルはBootstrapで用意されていないので、次のように設定します。
```scss:app/assets/stylesheets/application.scss
.alert-notice {
  @extend .alert-success;
}

.alert-alert {
  @extend .alert-danger;
}
```

次に、エラーメッセージでもアラートを利用します。
```erb:app/views/layouts/_error_messages.html.erb
<% if @post.errors.any? %>
  <% @post.errors.full_messages.each do |msg| %>
    <div class="alert alert-danger" role="alert">
      <a href="#" class="close" data-dismiss="alert">×</a>
      <%= msg %>
    </div>
  <% end %>
<% end %>
```
```scss:app/assets/stylesheets/application.scss
// 略
.field_with_errors {
  display: contents;

  input,
  texrarea {
    @extend .is-invalid;
}

// 略
```
元々はエラーの箇所のフィールドが赤枠になり、エラーメッセージがリスト形式で表示される形となっていました。

今回、Bootstrapのスタイルを利用したことによって、フラッシュとエラーメッセージが同じスタイルで表示され、フィールドに関しては、赤枠で囲まれ、！マークが右上に表示されるようになりました。
サーバーを立ち上げ、上記のように表示されているか、ぜひ確認することをお勧めします。

かなり長くなりましたが、これでメッセージ投稿アプリの完成です！

お疲れ様でした！