見出し画像

Profile機能を実装する。

こんにちは、わったんです。今回はプロフィール機能の実装について、まとめたことを、まとめていきます。

CarrierWaveのインストール

今回はファイルアップロード機能を提供してくれるgemである「CarrierWave」を使用します。

gem 'carrierwave', '2.0.2'

gemfileにコードを追記したら、

bundle install --path vendor/bundle

bundle installコマンドでgemをインストールします。これでCarrieWaveを使用できるようになりました。

アップローダーの作成

アップローダーとは、ファイル名やファイル保存先の取得に必要なクラスオブジェクトです。ファイルのアップロードに関する設定は、このアップローダーから操作できます。詳細は下のサイトを参考してください。

まず、アップローダーを作成します。

bundle exec rails g uploader Avatar

これでavatar.uploader.rbが作成されました。

class AvatarUploader < CarrierWave::Uploader::Base

 storage :file

 #アップロードファイルの保存先を指定
 def store_dir
   "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
 end

 #デフォルトの画像を指定(画像がアップロードされていない時用)
 def default_url
   'sample.jpg'
 end

 #アップロード可能なファイルの種類をホワイトリスト形式で指定する
 def extension_allowlist
   %w[jpg jpeg gif png]
 end
end

この作成されたファイルを上のように編集します。「store_dir」ではアップロードしたファイルの保存先を指定しています。このようにすることで、ファイルはpublic/uploads以下に保存できるようになります。「default_url」では画像がアップロードされていな時に表示されるデフォルトの画像をしてします。参照する画像はasset/images以下に配置しておきます。「extension_allowlist」ではアップロード可能なファイル形式を指定することができます。

Userテーブルに画像のカラムを追加する

次に画像urlを保存するためのカラムをuserテーブルに追加します。

bundle exec rails g migration AddAvatarToUser avatar:string

マイグレーションファイルを作成します。画像カラムに保存するデータはURL名になるので、カラムの型はstringになります。

class AddAvatarToUser < ActiveRecord::Migration[5.2]
 def change
   add_column :users, :avatar, :string
 end
end

マイグレーションファイルの中身は上のようになります。

bundle exec rails db:migrate
  schema.rb
  
  
  create_table "users", force: :cascade do |t|
   t.string "email", null: false
   t.string "crypted_password"
   t.string "salt"
   t.string "first_name", null: false
   t.string "last_name", null: false
   t.datetime "created_at", null: false
   t.datetime "updated_at", null: false
   t.string "avatar"
   t.index ["email"], name: "index_users_on_email", unique: true
  end

これで上のようにagatarカラムが追加されました。

user.rb

class User < ApplicationRecord
 authenticates_with_sorcery!
 #uploader使用の宣言
 mount_uploader :avatar, AvatarUploader

userモデルに「mount_uploader カラム名, 参照先アップローダークラス名」と記載することで、アップローダーとモデルを結びつけることができます。

ルーティングの設定

routes.rb


Rails.application.routes.draw do
 <省略>
 
 resource :profile, only: %i[edit show update]
end

単数形resourceを設定することで、ルーティングを追加します。追加するアクションはedit, show, updateの3つです。プロフィールは他の人のものをいじることはないので、単数形にします。

コントローラーの作成・編集

bundle exec rails g controller profiles show edit

profileコントローラーを作成します。このコントローラーにはshow, edit, updateの3つのアクションを持たせます。

Profiles_controller.rb


class ProfilesController < ApplicationController
 before_action :set_user
 def show; end

 def edit; end

 def update
   if @user.update(user_params)
     redirect_to profile_path, success: 'Profile was successfully updated.'
   else
     flash.now[:danger] = 'Failed to update the profile.'
     render :edit
   end
 end

 private

 #avatarカラムを持たせる
 def user_params
   params.require(:user).permit(:email, :last_name, :first_name, :avatar)
 end

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

コントローラを編集します。set_userは「@user = current_user」とはしないようにします。そうしないと、アップデートが失敗したときに、ビューに保存しようとした内容が表示されることがあるためです。

ビューの編集

最後にビューの編集をします。

show.html.erb


<div class="container pt-3">
 <div class="row">
   <div class="col-md-10 offset-md-1">
     <h1 class="float-left mb-5">プロフィール</h1>
     <%= link_to 'プロフィール編集', edit_profile_path, class: 'btn btn-success float-right' %>
     <table class="table">
       <tr>
         <th scope="row">メールアドレス</th>
         <td><%= current_user.email %></td>
       </tr>
       <tr>
         <th scope="row">氏名</th>
         <td><%= "#{current_user.last_name} #{current_user.first_name}" %></td>
       </tr>
       <tr>
         <th scope="row">アバター</th>
         <td><%= image_tag current_user.avatar_url, size: '40x40', class: 'rounded-circle mr15'%></td>
       </tr>
     </table>
   </div>
 </div>
</div>​
edit.html.erb


<div class="container">
 <div class="row">
   <div class="col-md-10 offset-md-1">
     <h1>プロフィール編集</h1>
     <%= 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 %>

       <div class='mt-3 mb-3'>

         <%= f.file_field :avatar, class: 'form-control mb-3', accept: 'image/*' %>
         <%= f.hidden_field :avatar_cache %>
       </div>
       <%= f.submit class: 'btn btn-primary' %>
     <% end %>
   </div>
 </div>
</div>

画像入力のところは、「accept」オプションでMIMEタイプを指定します。画像データや音声データごとに、データの表し方と読み取り方の決まり事があって、その決まり事がどれかを指定する感じでしょうか(多分)。今回は入力したデータを画像として認識するように指定しているのだと解釈しています。

以上で、簡単なプロフィールの設定ができました。

最後まで見てくださって、ありがとうございました。

いいなと思ったら応援しよう!