No_ideaのわからん日和

✏️...プログラミングが全然出来ない奴がわからんわからん言いながら様々な構文(記述方法やエラー構文など)と奮闘しながら成長していく成長記録です🐢

Ruby on Rails: チャットグループ機能(アイコン表示)の実装(CarrierWave使用)...chapter15

今日はusersテーブルとchat_groupsテーブルにアイコンを保存できるように各user_iconカラムとchat_group_iconカラムを追加したいと思います。

そして↓のようにユーザーページにアイコンを編集できるようにして、チャットグループでもアイコンを選べるようにして表示できるようにしていきたいと思います。

 

イメージ図:

 

やりたいこと

①DB設計(README)にアイコンを追加する

②カラム追加

③CarrierWaveの導入

④コントローラーの編集(chat_groups_controller.rb)

⑤ビューの編集(chat_groups/new.html.erb, edit.html.erb)

⑥コントローラーの編集(users_controller.rb)

⑦ルーティングの編集

⑧パスの変更

⑨ユーザーページの編集及び編集ページを作成

⑩ユーザーページのアイコンを表示

①①チャットグループへアイコンを表示

①②各アイコンを整える

 

①DB設計(README)にアイコンを追加する

## usersテーブル
|Column|Type|Options|
|------|----|-------|
|nickname|string|null: false|
|email|string|null: false|
|password|string|null: false|
|user_icon|string||
 
|Column|Type|Options|
|------|----|-------|
|chat_group_name|string|null: false|
|chat_group_description|text||
|chat_group_icon|string||

user_icon、chat_group_iconをstring型で追加します。

 

 

 

 

 

②カラム追加

各テーブルにアイコンを保存できるようにカラムを追加していきます。

最初はusersテーブルに追加していきます。

$rails g migration AddUser_iconToUsers user_icon:string

invoke  active_record

create    db/migrate/20200702130354_add_user_icon_to_users.rb

class AddUserIconToUsers < ActiveRecord::Migration[6.0]
 def change
  add_column :users, :user_icon, :string
 end
end

$rails db:migrate

https://gyazo.com/c86ff3c62fd5a9eaf928fc88c1e2adef

 

chat_groupsテーブルにも追加していきます。

$rails g migration AddChat_group_iconToChat_groups chat_group_icon:string

invoke  active_record

create    db/migrate/20200702131112_add_chat_group_icon_to_chat_groups.rb

class AddChatGroupIconToChatGroups < ActiveRecord::Migration[6.0]
 def change
  add_column :chat_groups, :chat_group_icon, :string
 end
end

$rails db:migrate

https://gyazo.com/09cb4fa9cf93f2b7ac75ebe0479af2f7

 

 

 

 

③CarrierWaveの導入

Gemfile

gem 'carrierwave'

$bundle install

$rails g uploader image

create  app/uploaders/image_uploader.rb

このファイルで保存方法を設定できる。

app/models/user.rb

class User < ApplicationRecord
 # Include default devise modules. Others available are:
 # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
 devise :database_authenticatable, :registerable,
 :recoverable, :rememberable, :validatable
 has_many :tweets
 has_many :chat_group_to_users
 has_many :chat_groups, through: :chat_group_to_users

 mount_uploader :user_icon, ImageUploader
end

mount_uploader :user_icon, ImageUploaderを追加。

 

app/models/chat_groups.rb

class ChatGroup < ApplicationRecord
 has_many :chat_group_to_users
 has_many :users, through: :chat_group_to_users

 
 mount_uploader :chat_group_icon, ImageUploader
end

mount_uploader :chat_group_icon, ImageUploaderを追加。

 

✍️ mount_uploader :(カラム名), (アップローダークラス)

modelに記述することにより画像をアップロードした際にImageUploaderクラスの設定を利用できるようになります。

アップロードされた画像はpublic/uploads下へ保存されます。

 

$rails s(再起動)

これで準備完了です。

 

参照:https://qiita.com/nekotanku/items/5da43600f35eada64eac

参照:https://qiita.com/ttaka66/items/264dcb85e41f9135685c

参照:https://pikawaka.com/rails/carrierwave

 

 

 

 

 

④コントローラーの編集(chat_groups_controller.rb)

app/controllers/chat_groups_controller.rb

https://gyazo.com/400d0245070037c7d38f6c7042832705

newメソッド

@chat_group_new.users << current_user

・current_user

ログインしているユーザー

・<<

尖っている方に開いている方の情報を付け加える(@chat_group_new.usersへ情報を付け加えている)

@chat_group_new

chat_groupsテーブルのインスタンス

・.users

.usersで@chat_group_newに所属しているusersテーブルのレコードを配列[]で取得できる。

これでログインしているユーザー(current_user)を@chat_group_new(chat_groupsテーブルのインスタンス).users)に加える(<<)ことができます。

 

https://gyazo.com/f2f6f12730330cdf45386fde83acf523

ストロングパラメーターに:chat_group_iconを追加。

 

 

 

 

 

 

⑤ビューの編集(chat_groups/new.html.erb,edit.html.erb)

先にチャットグループ新規作成でアイコンを保存できるようにしたいと思います。

https://gyazo.com/ff25eafa6a342e6903bb9e50284f79c4

 

file_fieldはファイル入力ボタンを作成します。

:chat_group_icon(カラム名)を指定して、今回はchat_group_iconカラムに保存できるようにしています。

http://localhost:3000/chat_groups/new

新規作成してみます。

 

 

次は編集ページでも画像をアップロードできるようにします。

https://gyazo.com/d5b0c16d4af5786991e79889786e4ca4

http://localhost:3000/chat_groups/8/edit

ファイルを選択できるようになったので編集してみます。

編集前:

編集後:

icon_kari.png → tsuki.png へ変更できているので成功です!

 

 

 

 

⑥コントローラーの編集(users_controller.rb)

https://gyazo.com/3624de02731658ae98959c22c20132d6

 

ユーザーページから『アカウント設定』リンクをはり、ニックネームとアイコンを編集できるようにしたいので、user_pageでログインしているユーザーのidを取得し、@user_infoに代入。

editメソッドでもユーザーのidを取得しインスタンス変数へ代入することで編集ページへ情報を渡せるようにしました。

そしてupdateメソッドでも同様にユーザー情報をedit_userへ代入し、ストロングパラメーター を通して、updateメソッドで編集した内容を保存できるようにしました。

ストロングパラメーターで許可したのは編集できるようにしたいnicknameとuser_iconをpermitに設定しました。

 

 

 

 

 

⑦ルーティングの編集

https://gyazo.com/4b069503182affd9b264961a63918bac

resourcesを使って一括に設定。

その中でも今回使うのはeditアクションとupdateアクションなのでonly: [:edit, :update]とすることでこの2つのルーティングを設定しました。

また、user_pageはonlyで設定できないので、追加したいアクションを記述できるcollectionを使ってブロック内に記述しました。

しかし、これだとprefixのpathが変わってしまうのでサインアップ、ログイン後のpathを変更しないといけません。

なので、変更していきます。

 

 

 

 

⑧パスの変更

app/controllers/application_controller.rb

def after_sign_in_path_for(resource)
 users_user_page_users_path
end

 

app/views/chat_groups/index.html.erb

<div class="chat-group__user-page">
 <%= link_to 'ユーザーページへ', users_user_page_users_path %>
</div>

 

 

 

 

 

 

⑨ユーザーページの編集及び編集ページを作成

先にユーザーページの編集をします。

https://gyazo.com/701067588f35ea73d4ad0753ed18f460

編集ページへのパスは/users/:id/editなのでlink_toメソッドを使用し、パスは"/users/#{@user_info.id}/edit"としました。

app/views/users/edit.html.erbを作成。

https://gyazo.com/80380b0b39a93fa5687765ac2b5b285a

updateへのpathは/users/:idなのでurl: "/users/#{@edit_user.id}"を設定。

また、form_withのデフォルトHTTP動詞はpostなのでmethod: :patchを設定。

ユーザーページから『アカウント設定』をクリック。

編集してみます。

https://gyazo.com/662fd586bfac5a928a26f2079b1c0bba

大丈夫そう。

 

 

 

 

 

 

⑩ユーザーページのアイコンを表示

ここで注意しなければならないのはアイコンを登録してないユーザーはデフォルトアイコン画像↓

f:id:No_idea:20200703095316p:plain

でなければならないことです。

なので最初にデバッグをしながら処理内容を決めていきたいと思います。

user_page.html.erb

<%= debug @user_info.user_icon.file%>

分かりやすいように一番下でdebugをしてみます。

@user_infoにはユーザー情報が含まれています。

その中でuser_iconのfileはどうかをアイコン登録者と未登録者で比較してみます。

アイコン登録者:

未登録者:

登録してあるユーザーではfile:のところにどこにアイコン画像が保存されているか書かれています。

しかし、未登録者では...となっていて何も書いていません(nil)。

これを使ってif文で分岐させて処理させれば良さそうです。

app/controllers/users_controller.rb

def user_page
 @user_info = User.find(current_user.id)

 if @user_info.user_icon.file != nil
  @user_icon = @user_info.user_icon.url
 else
  @user_icon = 'user_icon_default.png'
 end
end

fileがある、つまり登録者は@user_iconへアイコンのurl(どこへ保存されているか)の情報を代入。

未登録者では@user_iconへデフォルトアイコン画像を代入しています。

次にビューを編集していきます。

app/views/users/user_page.html.erb

image_tagに@user_iconとコードすることでアイコンのurlを代入します。

http://localhost:3000/users/users/user_page

登録あり:

 

登録なし:

ユーザーページでのユーザーアイコンの表示は問題なさそうです。

 

 

 

 

 

 

①①チャットグループへアイコンを表示

現在のチャットグループは↓のような表示になっています。

なのでチャットグループへアイコンを表示してみたいと思います。

イメージ図:

まだチャットグループへのメンバー登録機能は実装していないので、アイコンはグループ作成者のみアイコンが表示されるようにしたいと思います。

ここでも注意することがあります。先ほどと同様にアイコンを登録していない人はデフォルトアイコンを表示させるようにしなければなりません。

また、チャットグループのアイコンも同じで登録していない場合はデフォルトの画像を表示しなければなりません。

今回使用するチャットグループデフォルトアイコンは↓のものにしようと思います。

f:id:No_idea:20200703105918p:plain
それではやっていきたいと思います。

 

最初にチャットグループのアイコンが表示できるようにします。

app/controllers/chat_groups_controller.rb

def show
 @chat_group = ChatGroup.find(params[:id])
 
 if @chat_group.chat_group_icon.file != nil
  @chat_group_icon = @chat_group.chat_group_icon.url
 else
  @chat_group_icon = 'group_icon_default.png'
 end

end

ユーザーのアイコン表示と同じようにアイコンのファイルが何もない(nil)場合= 画像がある場合は@chat_group_iconにアイコンのurlを代入。

なければ@chat_group_iconにデフォルトアイコン画像を代入。

app/views/chat_groups/show.html.erb

 

登録あり:

 

登録なし:

アイコンを表示することに成功しました。

次にユーザーアイコンを表示させます。

app/controllres/chat_groups_controller.rb


def show
@chat_group = ChatGroup.find(params[:id])
 
    .
    . (省略)
    .
@chat_members = ChatGroupToUser.where(chat_group_id: @chat_group.id)
@chat_member_info = User.find(@chat_members.ids)
end

@chat_group

ここではchat_groupsテーブルから表示する情報をidから引っ張り出してきます。

これでレコード(横{行})が取得できました。

@chat_members

ここではwhereメソッドを使用し、chat_group_idカラムの中で@chat_group.id(表示したいページのid)を中間テーブル(chat_groupとuser)から探してきます。

これで同じチャットに参加しているメンバーのidも取得できるようになりました。

@chat_members_info

先ほどの@chat_membersを使用し、参加メンバーの情報を取得します。

@chat_members.idではなく@chat_members.idsで複数のユーザーの情報を取得できます。

app/views/chat_groups/show.html.erb

https://gyazo.com/92804441949ae74f811590bf8065ab64

ユーザーページのアイコンやチャットグループのアイコンのように1つだけの画像を表示ならばコントローラーへコードしインスタンス変数を持ってくれば大丈夫なのですが、2つ以上のアイコンを表示する場合、つまり情報を一つ一つ取り出す際はhtmlの方で分岐をコードしなければいけないみたいです。

each do |〇〇|で一つずつユーザー情報を取り出す処理をしています。

今は作成者のみですが、今後メンバー追加するときにこれでメンバーのアイコンを表示することができます。

コードできたので表示されるかやってみます。

登録あり:

登録なし:

できてます。

最後にアイコンを丸くし整えます。

 

 

 

 

①②各アイコンを整える

チャットグループでのアイコン(グループアイコン、ユーザーアイコン)を丸く表示したいので、今回は@mixinと@includeを使用してスタイル(今回は大きさと丸くするスタイル)を使い回したいと思います。

@mixinと@includeはセットで使用します。

これを使うと共通のスタイルが多い場合とかにコードが楽になります。

また、コードも見やすくなり一石二鳥です✌️

参照:https://stand-4u.com/css/sass/mixin.html

 

 

app/assets/stylesheets/chat_groupsフォルダを作成。

app/assets/stylesheets/mixinフォルダを作成。

app/assets/stylesheets/chat_groups/show.scssファイルを作成。

app/assets/stylesheets/mixin/_icon_setting.scssファイルを作成。

app/assets/stylesheets/application.scss

@import "mixin/icon_setting";
@import "users/user_page";
@import "chat_groups/show";

これで使えるscssが使用できるようになりました。

app/assets/stylesheets/chat_groups/show.scss

https://gyazo.com/5755c84bb5086403be8e4b4ad88b5297

大きさと丸みの設定してみました。

これでよかったら @mixinと@includeを使用して書いていきたいと思います。

app/assets/stylesheets/mixin/_icon_setting.scss

@mixin chat_icon {
 height: 50px;
 width: 50px;
 border-radius: 50%;
}

@mixin (任意の付けたい引数名){

  (処理内容)

}

 

app/assets/stylesheets/chat_groups/show.scss

https://gyazo.com/834e69f01ecf19a5e914d3966edc624a

@inculde (@mixinで付けた引数名);

これで@mixinから@inculdeにデータが引き継がれ使えるようになります。

では、ビューを確認してみます。

完成しました。

 

 

 

 

 

 

 

次回はチャットメンバーを追加できるように実装していきたいと思います。

その際に、インクリメンタルサーチ(入力した文字に該当する候補を出してくれる機能)と非同期通信(ページを遷移せずに一部だけを更新できる機能)を使用し追加できるようにします。

この2つスクールで学習してましたが、とりあえず完成させて提出したって感じで理解できないままやってましたね^^;

そのせいで実装に苦労しました。

このブログでもう一度実装し、記憶を定着させられるようにしたいと思います。

 

インクリメンタルサーチhttps://gyazo.com/f0f6a5b5ed8ebf2d6477373d0da548f9

 

 

非同期通信:https://gyazo.com/6644ad0a2b4eca5249326856dbb20ce7

 

 

 

 

 

 

 

以上です。