Railsを使ったToDoリストの作成(8.ログイン機能の実装)

#概要
本記事は、初学者がRailsを使ってToDoリストを作成する過程を記したものです。
私と同じく初学者の方で、Railsのアウトプット段階でつまづいている方に向けて基礎の基礎を押さえた解説をしております。
抜け漏れや説明不足など多々あるとは思いますが、読んでくださった方にとって少しでも役に立つ記事であれば幸いです。

#環境
* `Homebrew: 2.5.10` -> MacOSのパッケージ管理ツール
* `ruby: 2.6.5p114` -> Ruby
* `Rails: 6.0.3.4` -> Rails
* `node: 14.3.0` -> Node.js
* `yarn: 1.22.10` -> JSのパッケージ管理ツール
* `Bundler: 2.1.4` -> gemのバージョン管理ツール

```:iTerm
$ brew -v => Homebrew 2.5.10
$ ruby -v => ruby 2.6.5p114
$ rails -v => Rails 6.0.3.4
$ npm version => node: '14.3.0'
$ yarn -v => 1.22.10
$ Bundler -v => Bundler version 2.1.4
```

#第８章　Deviseを使ったユーザ認証機能の実装

第８章では、Railsのライブラリである[devise](https://github.com/heartcombo/devise)を使ってユーザ認証機能を実装していきます。

##1 deviseの設定を行う

まず、`Gemfile`にてdeviseを読み込みます。

```:Gemfile
gem 'devise'
```
>🙋‍♂️diviseというライブラリを読み込んでください
>->Gemfileに追記した時は必ず`iTerm`にて`$bundle install`を行う

`$bundle install`ができたらiTermにて以下のコマンドを入力しジェネレーターを実行します。

```:iTerm
$ rails generate devise:install
=>create  config/initializers/devise.rb
  create  config/locales/devise.en.yml
```
>🙋‍♂️ジェネレーターをインストールしてください
>💻configのinitializersに`devise.rb`というファイルを作成しました
>💻configのlocalesに`devise.en.yml`というファイルを作成しました

また、コンソールには上記２つのファイルを作成した旨に加え、以下４つの設定が必要である旨も表示されるため、指示に従い設定していきます。

①`config/environments/development.rb`に以下のようなメール設定に関する情報を入力します。

```development.rb
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
```
②`config/routes.rb`にroot_urlを設定します。

```routes.rb
Rails.application.routes.draw do
  root to: "home#index"
end
```
③`app/views/layouts/application.html.erb`にフラッシュメッセージが表示されるように設定します。

```enb:application.html.erb
<p class="notice"><%= notice %></p>
<p class="alert"><%= alert %></p>
```
④ログイン画面のHTMLテンプレートファイルを作成します。

```:iTerm
$ rails g devise:views
```

上記の設定が完了したら、最後にUserを管理するモデルを作成します。

```:iTerm
$ rails generate devise User
=>create db/migrate/20201114092712_devise_create_users.rb
  create app/models/user.rb
```
>🙋‍♂️Userを管理できるモデルを作成してください
>💻migrationファイル(データを作るためのテーブルを作成する場所)を作成しました
>💻userモデルを作成しました
>->migrationファイルを作成した場合は必ず`$rails db:migrate`でmigrationファイルを読み込む

※エラーが起こってしまう場合は定期的に`$rails s`でサーバを立ち上げ直しましょう。

ここまできたら以下のようなページ等が作成できているはずです。![スクリーンショット 2020-11-14 18.47.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864210/50d8ca38-b6c5-ec94-c029-77422b8ca793.png)

##2 ビュー
deviseの設定が終わったらビューの設定をしていきます。
deviseは初期設定がerbなので、まずはhamlに書き換えます。

既存のerbファイルをhamlに置き換えるためにはターミナルにて以下のコマンドを実行します。

```:iterm
$ bundle exec rake haml:replace_erbs
```

また、デフォルトではエラーメッセージなどが英語のままなので日本語化します。
日本語化するためには`config/locals`に`devise.ja.yml`ファイルを作り、ルールを記述します。

##3 ログイン状態によって表示を変更する
まずは、ログアウト機能を実装しましょう。

```haml:app/views/layouts/application.html.haml
= link_to 'Log out', destroy_user_session_path, data: { method: 'delete' }
```

[rails info](http://localhost:3000/rails/info/routes)で確認すると、userのログイン状況を削除するためには`destroy_user_session_path`を指定することがわかるので指定します。
link_toはデフォルトはGETリクエストのため、`data: { method: 'delete' }`を指定します。

では、次にログイン状態によって表示を変更できるよう条件分けしていきます。

```haml:app/views/layouts/application.html.haml
- if user_signed_in?
  .dropdown
    = image_tag 'default-avatar.png', class: 'header_avatar dropbtn'
    .dropdown-content
      %a{:href => "#"} Profile
      = link_to 'Log out', destroy_user_session_path, data: { method: 'delete' }
- else
  = link_to new_user_session_path, class: 'header_loginBtn' do
    = image_tag 'log-in.png'
```

ポイントは２つあります。

* `if user_signed_in?`でログイン時の状態を表示します。`user_signed_in?`メソッドがdeviseでは用意されており、ユーザがログインしているか否かを判断してくれます。
* ログインしていないときは`new_user_session_path`でログインページに遷移するようにします。

##4 一部機能をログイン時にしか操作できないようにする
投稿機能や編集機能や削除機能をログイン時のみ使えるようにしていきます。
コントローラに以下のように記述します。

```app/controllers/boards_controller.rb
before_action :authenticate_user!, only: [:new, :create, :edit, :update, :destroy]
```

`authenticate_user!`はdeviseが用意してくれているメソッドでログインしているユーザのみ操作を許可し、ログインしていない場合はログイン画面に遷移するようにしてくれます。
beeforeアクションを使うことで各アクションの前にログイン状況を判断できるようにします。
しかし、Read機能はログインしていなくてもできるようにしたいので、onlyオプションで対象を絞っています。