【Ruby on Rails】gemのdeviseを使用し、名前とパスワードのみでログインする方法

# 目標
![画面収録 2020-09-01 22.17.23.mov.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700999/4fedaa4a-1510-7a49-4675-22b845a7280d.gif)
# 開発環境
ruby 2.5.7
Rails 5.2.4.3
OS: macOS Catalina
# 前提

※　▶◯◯　を選択すると、説明等が出てきますので、
　　よくわからない場合の参考にしていただければと思います。

homesコントローラーを作成し、以下を記述済。

```rb:config/routes.rb
root 'homes#top'
get 'mypage', to: 'homes#mypage'
```
```rb:app/controllers/homes_controller.rb
class HomesController < ApplicationController
 def top
 end
 def mypage
 end
end
```

# 1,deviseをインストールする

Gemfileの最後に、以下を追加。

```rb:Gemfile

gem 'devise'
```
保存後、ターミナルに移動し、下記を実行。

```:ターミナル
$ bundle install
```

```:ターミナル
$ rails g devise:install
```
<details><summary>解説</summary>
rails g devise:install は deviseの初期設定を行います。</details>


以下のような表示がされればOKです。

```:ターミナル
===============================================================================

Depending on your application's configuration some manual setup may be required:

  1. Ensure you have defined default url options in your environments files. Here
     is an example of default_url_options appropriate for a development environment
     in config/environments/development.rb:

       config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

     In production, :host should be set to the actual host of your application.

     * Required for all applications. *

  2. Ensure you have defined root_url to *something* in your config/routes.rb.
     For example:

       root to: "home#index"
     
     * Not required for API-only Applications *

  3. Ensure you have flash messages in app/views/layouts/application.html.erb.
     For example:

       <p class="notice"><%= notice %></p>
       <p class="alert"><%= alert %></p>

     * Not required for API-only Applications *

  4. You can copy Devise views (for customization) to your app by running:

       rails g devise:views
       
     * Not required *

===============================================================================
```

<details><summary>エラー時</summary>
エラーが表示された場合は、Railsのアップデートによるエラーの可能性が高いため、
Gemfileのgem 'sqlite3'を見直してください。</details>

# 2,ログイン画面を表示する

## テーブルの作成（名前の追加）
通常時の記述とは異なり、
deviseの独自ルールである「rails g devise モデル名」と記述。
今回はUserモデルを作成するため、ターミナル上で下記を実行。

```:ターミナル
$ rails g devise User
```
下記フォルダにて、t.string :name　を記述。

```rb:db/migrate/xxxxxxxxxxxxx_devise_create_users.rb
...

      t.string :name 　# ←ここに追加
      t.timestamps null: false
    end

    add_index :users, :email,                unique: true
    add_index :users, :reset_password_token, unique: true
    # add_index :users, :confirmation_token,   unique: true
    # add_index :users, :unlock_token,         unique: true
  end
end

```
<details><summary>補足１</summary>
null: falseを記述することで、空の状態での保存を防ぎます。
null: falseについては[こちら](https://qiita.com/ryuuuuuuuuuu/items/2841cddf8b541c336ebd)</details>

<details><summary>補足２</summary>
名前以外でも登録情報を追加したい場合は、
t.string :nameと同じように記述することで可能。
ex) t.string :phone_number など</details>

その後ターミナルに移動し、下記を実行。

```:ターミナル
$ rails db:migrate
```
以下のような表示がされればOKです。

```:ターミナル
== 20200901103907 DeviseCreateUsers: migrating ================================
-- create_table(:users)
   -> 0.0038s
-- add_index(:users, :email, {:unique=>true})
   -> 0.0013s
-- add_index(:users, :reset_password_token, {:unique=>true})
   -> 0.0013s
== 20200901103907 DeviseCreateUsers: migrated (0.0067s) =======================
```
## viewの作成（名前の追加）
```:ターミナル
$ rails g devise:views users
```
<details><summary>解説</summary>
rails g devise:views usersとすることで、
app/views/usersの中にdeviseのviewsを格納可能。
viewsの編集も可能。</details>

3行目にある<%= form_for %>の中に以下を記述。

```erb:app/views/devise/registrations/new.html.erb
...

  <div class="field">
    <%= f.label :name %><br />
    <%= f.text_field :name, autofocus: true, autocomplete: "name" %>
  </div>

...
```
下記のemailの3箇所をnameに, email_fieldをtext_field に変更

```erb:app/views/devise/sessions/new.html.erb
  <div class="field">
    <%= f.label :email %><br />
    <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
  </div>
  
　　↓

  <div class="field">
    <%= f.label :name %><br />
    <%= f.text_field :name, autofocus: true, autocomplete: "name" %>
  </div>

```
49行目付近にある下記記述をコメントアウト外して[:email]を[:name]に変更

```rb:config/initializers/devise.rb

config.authentication_keys = [:name]
```
##　ログイン前のview
```erb:app/views/homes/top.html.erb
<%= link_to '新規登録', new_user_registration_path %><br>
<%= link_to 'ログイン', new_user_session_path %>
```
##　ログイン後のview
```erb:app/views/homes/mypage.html.erb
<%= current_user.name %><br>
<%= current_user.email %><br>
<%= link_to 'ログアウト', destroy_user_session_path, method: :delete %>
```
<details><summary>解説</summary>
current_userはdeviseのヘルパーメソッドであり、ログイン中のユーザー情報を取得可能。
ログアウト時はhttpメソッドでの被りはないものの、
method: :deleteを指定してあげると確実。</details>

# 3,コントローラーの作成
```:ターミナル
$ rails g devise:controllers users
```

4行目,44〜46行目,54〜56行目をコメントアウトを外し、
45行目の:attributeを:name, :emailに変更。
55行目のsuper(resource)を飛ばしたいpathに変更。

```rb:app/controllers/users/registrations_controller.rb
# frozen_string_literal: true

class Users::RegistrationsController < Devise::RegistrationsController
  before_action :configure_sign_up_params, only: [:create]
  # before_action :configure_account_update_params, only: [:update]

...

  # protected

  # If you have extra params to permit, append them to the sanitizer.
  def configure_sign_up_params
    devise_parameter_sanitizer.permit(:sign_up, keys: [:name, :email])
  end

  # If you have extra params to permit, append them to the sanitizer.
  # def configure_account_update_params
  #   devise_parameter_sanitizer.permit(:account_update, keys: [:attribute])
  # end

  # The path used after sign up.
  def after_sign_up_path_for(resource)
    mypage_path
  end

  # The path used after sign up for inactive accounts.
  # def after_inactive_sign_up_path_for(resource)
  #   super(resource)
  # end
end

```
<details><summary>解説</summary>
44〜46行目で新規会員登録時のカラムの保存許可を指定。
55〜56行目で新規会員登録後の遷移先を指定。</details>


<details><summary>補足</summary>会員情報更新後の遷移先も上記のようにすれば変更可能。記述は57行目以下でOK。
　def after_update_path_for(resource)
　　mypage_path
　end
</details>

27行目以下に追加。

```rb:app/controllers/users/sessions_controller.rb
...

  def after_sign_in_path_for(resource)
    mypage_path
  end

  def after_sign_out_path_for(resource)
    root_path
  end
end

```
<details><summary>解説</summary>
ログイン時、ログアウト時の遷移先指定。</details>

devise_for :users 以下に追加記述。

```rb:config/routes.rb
Rails.application.routes.draw do
  devise_for :users, controllers: {
    sessions: 'users/sessions',
    registrations: 'users/registrations',
  }
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html

  root 'homes#top'
  get 'mypage', to: 'homes#mypage'
end

```

# P.S.
twitterではQiitaにはアップしていない技術や考え方もアップしていますので、
よければフォローして頂けると嬉しいです。
詳しくはこちら　https://twitter.com/japwork