【Rails】プロフィール詳細・編集機能の実装

##機能の実装
プロフィールの詳細ページの表示と編集機能の実装を行なっていく。

**手順**
①ルーティングの記載
②イメージカラム（プロフ写真用）の追加
③コントローラー記載
④uploaderファイルの作成
⑤viewの表記

##①ルーティングの記載
プロフィールのルーティングには複数形のではなく、単数系の``resource``を利用する。

複数作成できる掲示板(Board)などの仕様と異なり、ユーザーに対するプロフィールは1つしか存在しない。
また他ユーザーのプロフィールを編集することはないので、**idを表示させるメリットがない。**

詳細ページでidを表示させると自分が何番目に作成されたユーザーか分かってしまうリスクがあり、``詳細ページ(show：/profiles/:id)``に他ユーザーのidを入力されてしまうこともあるので、``単数形リソースを使うことが望ましい。``

```routes.rb
resource :profile,only: %i[show edit update]
```

##②イメージカラム（プロフ写真用）の追加
ターミナルにて``userテーブル``にプロフィール写真を保存するカラムを用意する。ここでは``userテーブル``に後から追加するような形でコマンドを行う。

今回はカラム名を``avatar``で登録。
新たに作成されたマイグレーションファイルに下記を記入し``rails db:migrate``を行う。


```ターミナル.
rails g migration add_avatar_to_users avatar:string  
```

```add_avatar_to_users.rb
 def change
    add_column :users, :avatar, :string
 end
```

##③コントローラー記載
``profiles_controller.rb``を作成し、下記を記入。

```ターミナル.
rails g controller profiles
```

```profiles_controller.rb
class ProfilesController < ApplicationController
    before_action :set_user,only: %i[edit update]

    def edit
    end

    def update
        if @user.update(user_params)
            redirect_to profile_path,success: "ユーザーを更新しました"
        else
            flash.now[:danger] = "ユーザーを更新できませんでした"
            render :edit
        end
    end

    private
    def set_user
        @user = User.find(current_user.id)
    end

    def user_params
        params.require(:user).permit(:email,:first_name,:last_name,:avater,:avater_cash)
    end
end
```

##④uploaderファイルの作成
``uploaderファイル``については[Carrierwaveを使った画像アップロード機能](https://qiita.com/mmaumtjgj/items/509eed8e52ae53c4b41a)の実装を終えた前提で進める。

``avatar_uploader.rb``を作成したいので、ターミナルにてコマンド実施。

```ターミナル.
rails g uploader avatar
```

次に``userモデル``と``uploader``を紐付けたいので、``userモデル``に下記を追加。

```user.rb
mount_uploader :avatar, AvatarUploader
```

プロフ写真の細かい設定を行うので、``avatar_uploader.rb``を編集。
デフォルトでほとんどコメントアウトされているので、設定したいものだけコメントアウトを外し編集する。

今回の設定は
・画像をアップロードできること
・アップロードした画像の表示
・デフォルト画像の設定
・アップロードファイルの指定をする

```avatar_uploader.rb
#画像をアップロード
  storage :file

#アップロードした画像の表示
  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end

#デフォルト画像の設定
 def default_url
  "default.png"　　←デフォルト画像に設定したい画像名を記入
 end

#アップロードファイルの指定
　　def extension_allowlist
    %w(jpg jpeg gif png)
　　end
```

##⑤viewの表記

```show.html.rb
<%= link_to '編集', edit_profile_path, class: 'btn btn-success float-right' %>
      <table class="table">
        <tr>
          <th scope="row"><%= t(User.human_attribute_name(:email)) %></th>
          <td><%= current_user.email %></td>
        </tr>
        <tr>
          <th scope="row"><%= t(User.human_attribute_name(:full_name)) %></th>
          <td><%= current_user.decorate.full_name %></td>
        </tr>
        <tr>
          <th scope="row"><%= t(User.human_attribute_name(:avatar)) %></th>
          <td><%= image_tag current_user.avatar.url, class: 'rounded-circle', size: '50x50' %></td>
        </tr>
      </table>
```



```edit.html.rb
<%= form_with model: @user, url: profile_path, local: true do |f| %>
   <%= render 'shared/error_messages', object: f.object %>
   <%= f.label :email %>
   <%= f.email_field :email, class: 'form-control mb-3' %>

   <%= f.label :last_name %>
   <%= f.text_field :last_name, class: 'form-control mb-3' %>

   <%= f.label :first_name %>
   <%= f.text_field :first_name, class: 'form-control mb-3' %>

   <%= f.label :avatar %>
   <%= f.file_field :avatar,class: 'form-control mb-3', accept: 'image/*' %>
   <%= f.hidden_field :avatar_cache %>

   <%= f.submit "更新", class: "btn btn-primary"%>
<%end%>
```

``↑editファイル``にて``current_user``ではなく``@user``を使っている理由として、
例えばプロフィール名の変更に失敗した際に、画面上でプロフィールとして表示される名前が変わってししまう。
これはプロフィール編集の失敗時に``current_user``が``update``の影響を受けてしまうため``@user``での導入が望ましい。

``accept: 'image/*'``とは、input要素のaccept属性であり、サーバーが受け入れるファイルの種類を指定する属性。
``image/*``と表記することで、画像ファイル全般を指定できる。
▶︎[その他acceptについて](http://html5.cyberlab.info/elements/forms/input-accept.html)

##参考記事
[プロフィール編集機能の実装](https://qiita.com/kidokoro-syusei/items/333ecab2d936b5ee9586)