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タイプを指定します。画像データや音声データごとに、データの表し方と読み取り方の決まり事があって、その決まり事がどれかを指定する感じでしょうか(多分)。今回は入力したデータを画像として認識するように指定しているのだと解釈しています。
以上で、簡単なプロフィールの設定ができました。
最後まで見てくださって、ありがとうございました。