【学習】devise ユーザー情報表示・編集・削除機能


deviseを今回初めて実装。
新規登録、ログインログアウトに関する機能の実装を終えている段階です。
今回はユーザー情報の表示（マイページ）と編集・削除機能の実装を行っていきたいと思います。

## 環境
- Windows, WSL
- Docker
- Ruby 3.2.3
- Rails 7.1.3



## 参考記事を元に実装
https://plog.kobacchi.com/rails-devise-user-profile-customize/#index_id10

基本上記記事を参考に進めていきます。
#### 1：プロフィール画面に関するコントローラーやビューファイルの作成
まずは下記コマンドで`UsersController`を作成し、`show`アクションとそれに対応する` show.html.erb`ビューファイルを用意。
```
$ docker compose exec web rails g controller Users show
```

#### 2：生成した`users_controller.rb`を編集
```
class UsersController < ApplicationController
  def show
    @user = current_user
  end
end
```

#### 3：生成した`app/views/users/show.html.erb`ファイル編集
```
<div class="flex justify-center items-center mt-6">
  <div id="profile" class="card w-80 md:w-96 bg-base-100 shadow-xl">
    <figure class="px-10 pt-10">
      <div class="avatar">
        <div class="w-24 rounded-full border-4 mx-auto mt-4">
          <%= image_tag(current_user.avatar_url.presence || "default_avatar.png", alt: "Avatar Placeholder") %>
        </div>
      </div>
    </figure>
    <div class="card-body items-center text-center">
      <h2 class="card-title"><%= current_user.name %></h2>
      <p class="text-base-content text-opacity-70">
        <%= current_user.email %>
      </p>
      <div class="card-actions">
        <%= link_to "編集", edit_user_registration_path, class: "text-base-content btn btn-primary", data: { turbo_stream: true } %>
      </div>
    </div>
    <div class="flex justify-end pr-5 pb-4">
      <%= link_to "アカウント削除", user_registration_path, class: "text-base-content btn btn-error btn-sm bg-opacity-90", data: { turbo_method: :delete, turbo_confirm: "本当にアカウントを削除しますか" } %>
    </div>
  </div>
</div>
```

- **`current_user.name`と`current_user.email`**
    - `current_user`の情報から、ログインしているユーザーの名前とメールアドレスを表示します。これにより、他のユーザー情報にアクセスせずに、シンプルな情報が表示できます。
    - Deviseがcurrent_userを自動的に設定しているため、コントローラやビューでcurrent_userを記載するだけで、現在ログインしているユーザーの情報が取得できます。例えば、current_user.nameでそのユーザーの名前が取得でき、current_user.emailでメールアドレスが取得できます。
- **編集リンクの設定**
    - `edit_user_registration_path`：`Devise`で提供されているユーザー編集用のルートで、自動的に現在のユーザーの登録情報を編集できる画面に移動します。
- **アカウント削除リンク**
    - `user_registration_path`は、`Devise`のルートで、削除メソッドと確認メッセージも設定されています。


#### 4：ルーティング設定
```
Rails.application.routes.draw do
  get 'users/show', to: 'users#show', as: 'profile'
```
もしくは
```
  # プロフィールページのルート
  resource :users, only: [] do
    get 'profile', to: 'users#show', as: 'profile'
  end
```
👆`resource :users, only: [:show, :edit, :destroy, :update] do` ブロックを使うと、`users` のリソースに関する基本的なルーティングを一括で設定できます。しかし、Devise を使用している場合、Devise が自動的にユーザーの認証と登録に関連するルーティングを提供してくれます。そのため、Devise のユーザーリソースと競合を避けるために、標準の `resource :users` を使うと複雑になる可能性があるんです。

ただし、マイページではなく「プロフィール」ページに変更したい場合は、Devise のルーティングと共存させつつ、カスタムのルーティングを追加できます。

※プロフィール（若しくはマイページ）へのリンク設定は個々人異なると思うので適切なものに変更してください

#### 5：パスワードなしでユーザー情報を編集できるようにする
`devise`では（めんどくさいことに）ユーザー情報変更の際、初期設定ではパスワードを求められるようになっています。
👇枠がなくてわかりづらいのですが、確かにパスワード入力欄がデフォルトで設定されている状態。
[![Image from Gyazo](https://i.gyazo.com/269a44ff87f7c861482a0cc14c47387c.png)](https://gyazo.com/269a44ff87f7c861482a0cc14c47387c)

なので、下記ファイルに次のように入力します

```app/controllers/users/registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController

  protected
  def update_resource(resource, params)
    resource.update_without_password(params)
  end
end
```

#### 6：プロフィール編集後にマイページへリダイレクトさせる
Deviseの仕様上、デフォルトのままだとユーザー情報（プロフィール）をアップデートしたとき、自動的にトップページにリダイレクトされてしまうそうなので設定を編集していきます

プロフィールを更新後はプロフィール画面（マイページ）にリダイレクトされるよう変更する為下記ファイルにコードを追記
```app/controllers/users/registrations_controller.rb
  def after_update_path_for(resource)
    # 自分で設定した「マイページ」へのパス
    users_profile_path
  end

  #私の場合プロフィール表示のルーティングは以下のようになっています
  get 'users/show', to: 'users#show', as: 'profile'

  # つまり、「users_profile_path」は以下のように変更
  profile_path
```

#### 7：ユーザー情報編集画面の修正
`devise`を導入した時、自動で生成されているユーザー情報編集画面。
場所は`app/views/devise/registrations/edit.html.erb`になるかと思います。
こちらのファイルを最後にパスワードなしでも更新可能となるようご自身が好きなスタイルにすればユーザー情報編集画面は完了です。（削除ボタンもすでにセットされている！）

## 補足1：`form_for`と`form_with`
### 1. `form_for` のコード
```
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put, class: 'w-full max-w-md' }) do |f| %>
```

### コードの意味
- **`form_for`**: Railsのフォームヘルパーの一つで、特定のリソース（ここではユーザー）を更新するためのフォームを作成
- **`resource`**: この変数は、フォームが対象とするデータ（ここではユーザー）を指す
- **`as: resource_name`**: フォームのフィールド名を指定することで、生成されるHTMLの名前属性がリソースに基づいて設定される
- **`url: registration_path(resource_name)`**: フォームが送信されるURLを指定。ここでは、ユーザーの登録または更新を行うためのパスを指定。
- **`html: { method: :put, class: 'w-full max-w-md' }`**:
    - **`method: :put`**: フォームが送信されるときにHTTPメソッドとして `PUT` を使用します。これは、リソース（ユーザーデータ）の更新を意味している。
    - **`class: 'w-full max-w-md'`**: このフォームのCSSクラスを指定します。`w-full` は幅を100%に、`max-w-md` は最大幅を設定。

### 2. `form_with` のコード
```
<%= form_with model: user, url: mypage_path, method: :put do |f| %>
```

### コードの意味
- **`form_with`**: Railsの新しいフォームヘルパーで、特定のモデル（ここではユーザー）を使用してフォームを作成。
- **`model: user`**: このモデルは、フォームが対象とするデータを指定。この場合、`user` という変数に格納されたユーザー情報を使用。
- **`url: mypage_path`**: フォームが送信されるURLを指定。ここでは、マイページのパスに送信している。
- **`method: :put`**: フォームが送信されるときにHTTPメソッドとして `PUT` を使用。


**★ここまでのまとめ：`form_for` は特定のリソースに基づいて簡単にフォームを作成するのに対し、`form_with` はより柔軟で、特に非同期処理に適している**


## 補足2：ulrとdevise生成ルートについて
**★`url: mypage_path`**
- `url: mypage_path`の場合、Railsは `mypage` に対応するURLを生成
- もしアプリケーションのルートURLが `https://example.com` だとすると、最終的には以下のようなURLになる
    ```arduino
    https://example.com/mypage
    ```
- `mypage_path` は、`config/routes.rb` で設定されたルーティングに基づいているため、正しく設定されているかを確認することが重要

<br>

**★`url: registration_path(resource_name)`**
- `url: registration_path(resource_name)` は、Deviseを使用している場合に特にルーティングファイルで設定しなくても、Deviseが自動的に必要なルートを生成してくれる！！

#### Deviseが生成するルート
Deviseを使うと、`devise_for :users` の一行で、以下のようなルーティングが自動的に設定されます：
- 新規登録用のルート
- ユーザー情報の更新用のルート
- ログイン、ログアウト用のルート
- パスワードリセット用のルート

このため、`registration_path(resource_name)` や `new_registration_path(resource_name)` といったメソッドを使うことで、登録や更新のURLを簡単に生成できる！！

### URLの具体例
例えば、`registration_path(:user)` の場合、通常は次のようなURLが生成されることになる

- **POST リクエストの場合**（新規登録）：
    ```arduino
    POST https://yourdomain.com/users
    ```
    
- **PUT リクエストの場合**（ユーザー情報の更新）：
    ```arduino
    PUT https://yourdomain.com/users
    ```
https://qiita.com/beanzou/items/1ff9c7cba61fd1fa5c80。


https://github.com/heartcombo/devise


## さいごにまとめ
`devise`のもとからある機能を上手に利用してコントローラー、ビューファイルをメインに無事にユーザー情報のメインと編集、削除機能を実装することができました。
既に作成されているのは確かにうれしい。ですが、そこからどうやって自分の望むものに編集していくか。楽しさもありつつ、難しさも感じました。
今回の記事が何か参考になれば幸いです。