【Rails7】deviseを使用したログイン機能の作成

Rails、Rubyを学習中の者です。
備忘録として記事を作成します。
間違っているところも多々あると思いますので、その際はコメントなどでご教授いただけますと幸いです。

### deviseとは
Railsアプリケーションにおいて、比較的簡単に認証機能を導入できるgemです。
デフォルトではメール（email）で認証を行います。
比較的簡単とはいえRailsの知識が必要ですので、初めてRailsでアプリを構築する方は先に自分で認証システムを作ってみることをお勧めします（公式のgithubでも推奨されています）。

### 環境
Windows11
Ubuntu 22.04.4 LTS
Ruby 3.1.4
Rails 7.0.8.6

### 今回の実装の目標
- deviseを用いた認証機能の構築
- ユーザーネームでログイン・認証ができるようにする

### 作業の流れ
- gemの追加
- ジェネレータのインストールと各種設定の変更
- モデルの作成
- ビューの設定
- 設定ファイルの編集

### gemの追加
```
# Gemfile
gem "devise", "~> 4.9"
```
Gemfile内にgemを配置して、"bundle install"します。
今回はDockerを使用しての開発になりますので、下記"web"には任意のイメージ名を対応させてください。
```
# ターミナル
$ docker compose exec web bundle install
```
インストールが終了したら、サーバーを再起動します。

```
# ターミナル
$ docker compose restart
```

### ジェネレータのインストールと各種設定の変更
サーバーの再起動が終了したら、ジェネレータをインストールします。
```
# ターミナル
$ docker compose exec web rails generate devise:install
```
インストールが終わると、英語で指示が出てきますので、それに従って各種ファイルを変更します。
特に最初の、routes.rbでrootパスを指定しないとエラーになります。
任意のrootパスを指定してください。


### モデルの作成
任意のモデルにdeviseを追加します。
今回は、Userモデルにdeviseを追加します。
```
# ターミナル
$ docker compose exec web rails generate devise MODEL名

# 今回の実装
$ docker compose exec web rails generate devise user
```
ファイルがいくつか生成されます。
今回は、ユーザーネームでログインしたいので、生成されたマイグレーションファイルの中に"user_name"カラムを追加します。
```
# 2024#######_devise_create_users
class DeviseCreateUsers < ActiveRecord::Migration[7.0]
  def change
    create_table :users do |t|
      ## Database authenticatable
      t.string :email,              null: false, default: ""
      t.string :encrypted_password, null: false, default: ""

      # deviseでユーザーログインできるようにカラムを追加
      t.string :user_name,          null: false

      ## Recoverable
      t.string   :reset_password_token
      t.datetime :reset_password_sent_at

      ## Rememberable
      t.datetime :remember_created_at

      ## Trackable
      # t.integer  :sign_in_count, default: 0, null: false
      # t.datetime :current_sign_in_at
      # t.datetime :last_sign_in_at
      # t.string   :current_sign_in_ip
      # t.string   :last_sign_in_ip

      ## Confirmable
      # t.string   :confirmation_token
      # t.datetime :confirmed_at
      # t.datetime :confirmation_sent_at
      # t.string   :unconfirmed_email # Only if using reconfirmable

      ## Lockable
      # t.integer  :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
      # t.string   :unlock_token # Only if unlock strategy is :email or :both
      # t.datetime :locked_at


      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
```
マイグレーションファイルを修正したら、以下のコードを実行してデータベースに反映させます。
```
# ターミナル
$ docker compose exec web rails db:migrate
```

### ビューの設定
deviseではデフォルトだとログイン画面などのビューファイルが編集できません。
したがって、下記コードを実行しファイルを編集できるようにします。
今回は、ログイン画面のみ編集したいので、ログイン画面に関わる "-v sessions"オプションをつけて実行します。
```
# ターミナル
$ docker compose exec web rails generate devise:views user_sessions -v sessions
```
app/views/"任意のフォルダ"/sessions/new.html.erb　というフォルダ、ファイルが生成されているので、こちらを編集します。
emailのフィールドを削除して、ユーザーネームのフィールドを作成します。
```
# app/views/user_sessions/sessions/new.html.erb
  <div class="field">
    <%= f.label :user_name %><br />
    <%= f.text_field :user_name, autofocus: true, autocomplete: "user_name" %>
  </div>

```
以上でログインフォームが完成しました。

### 設定ファイルの編集
実際にdeviseでユーザー名（Userモデルのuser_name）で認証できるように、deviseの設定をを変更します。
```
# config/initializers/devise.rb

# 以下のコメントアウトを外す
# config.authentication_keys = [:email]

# 外したらパラメータを[:email]から[:user_name]
 config.authentication_keys = [:user_name]
```
ここまで設定出来たら、サーバーを再起動させて設定を反映させます。

```
# ターミナル
$ docker compose restart
```

以上で完成です！
お疲れさまでした。

### 感想
思っていたより簡単に実装できたので良かったです。


参考（順不同）
https://github.com/heartcombo/devise
https://qiita.com/yuki82511988/items/73659af9d1049bd1b256
https://qiita.com/yoyoyoheyheyhey/items/582cc071b3e0a8a2b583