No_ideaのわからん日和

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

Ruby on Rails: チャットメッセージ実装(フォームから投稿・保存まで)...chapter18-1

①チャットメッセージモデルを作成

$rails g model chat_message

https://gyazo.com/249510f902ab1ea526b27c5f2c82282f

 

 

マイグレーションファイルの編集&マイグレーションを実行

先ほど作成したマイグレーションファイルを編集します。

class CreateChatMessages < ActiveRecord::Migration[6.0]
 def change
  create_table :chat_messages do |t|
   t.text :message
   t.string :image
   t.references :user, foreign_key: true
   t.references :chat_group, foreign_key: true

   t.timestamps
  end
 end
end

メッセージ(messageカラム)はtext型で作成し、次の画像のみでも投稿できるようにしたいので、オプションは特につけません。

 

画像(imageカラム)はstring型で作成。メッセージ同様、メッセージだけでも投稿できるようにしたいので、オプションは特につけません。

 

ユーザー(user)をidで管理したいので、user_idを自動的に生成してくれるreferencesを使用しました。referencesを使うことによってforeign_keyが使用できるようになったのでtrueとして外部キー制約を使えるようにします。

これでメッセージを送った時に、ユーザーの情報(idやアイコン、ニックネームなど)が使用できるようになります。

 

チャットグループ(chat_group)をidごとに管理します。

これでチャットグループごとにメッセージが管理できるようになります。

ユーザー(user)同様にreferencesを使用し、chat_group_idを自動生成。

外部キー制約を使用するためにforeign_keyをtrue。

 

 

設定が終わったので、マイグレーションを実行します。

$rails db:migrate

https://gyazo.com/27915e30907f4bf12466282fa147b31d

 

 

 

③modelの編集

chat_message、user、chat_groupの各モデルを編集します。

それぞれの関係図:

https://gyazo.com/43848817a55b81b3507577d42885536b

一人のユーザーは沢山のグループを持つことができ、沢山のメッセージを書き込むことができます。

 

chat_message.rb

class ChatMessage < ApplicationRecord
 belongs_to :user
 belongs_to :chat_group
end

上の図の通り、一人の人が沢山のメッセージを書き込めるので、userモデルはbelongs_toを使用。

また、チャットグループも同様で、1つのチャットグループは沢山のメッセージを持っているのでチャットグループの関係性はbelongs_to。

 

 

chat_group.rb

class ChatGroup < ApplicationRecord
has_many :chat_group_to_users
has_many :users, through: :chat_group_to_users
has_many :chat_messages, dependent: :destroy

mount_uploader :chat_group_icon, ImageUploader
end

チャットグループは沢山のメッセージを持てるので、chat_messagesはhas_many。

また、dependentオプションでdestroyを設定することで、チャットグループを削除された時にメッセージも削除されます。

 

user.rb

class User < ApplicationRecord
 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
has_many :chat_messages, dependent: :destroy

mount_uploader :user_icon, ImageUploader
end

userモデルでもチャットグループと同様に1人のユーザーは沢山のチャットで沢山のメッセージを書き込めるのでchat_messageモデルとの関係性はhas_many。

また、dependentオプションでdestroyを設定することでユーザーを削除した時にメッセージも削除されます。

 

dependent: :destroyの使い方

▶︎ https://dorarep.page/articles/rails-dependent

 

 

 

④チャットメッセージコントローラーを作成

$rails controller chat_messages

https://gyazo.com/66193b134aada78b1d3e1103315d83e0

 

 

 

⑤ルーティングを設定

routes.rb

resources :chat_groups do
 resources :chat_messages, only: [:index, :create, :destroy]
end

chat_groupsと紐づけたいのでchat_messagesをネストしました。

また、メッセージページの表示、メッセージの作成、チャットグループを削除をできるようにしたいのでonlyメソッドを使用しindex, create, destroyの3つのアクションを追加できるようにしました。

このdestroyはチャットグループを削除したときに、このアクションがなければエラーが起こります。

理由としては、チャットグループを削除したのにメッセージが残っていると混乱が起きるためです。

 

 

 

⑥indexアクションをchat_messages_controllerへ追加

class ChatMessagesController < ApplicationController
 def index
 end
end

 

 

 

⑦index.html.erbを作成

app/views/chat_messages/index.html.erbを作成します。

 

 

 

⑧チャットグループ詳細ページからチャットページへのリンクを作成

$rails routes

https://gyazo.com/e0cbfeff734d704d26275c70eef99f98

/chat_groups/:chat_group_id/chat_messages(.:format)

がチャットメッセージのpathなので。。。

<div class="chat-group-show__talk-in">
 <%= link_to "トーク", "/chat_groups/#{@chat_group.id}/chat_messages" %>
</div>

@chat_group.idでchat_groups_controller.rbのshowアクションで取得したチャットグループ情報のidを取得しています。

 

 

 

⑨遷移できているか確認

遷移できるようになりました。

 

 

 

⑩コントローラーのindexアクションの処理内容を設定

app/controllers/chat_messages_controller.rb

def index
 @group = ChatGroup.find(params[:chat_group_id])
end

各チャットグループ情報をビューで使えるように編集します。

 

 

 

①①index.html.erbを編集(チャットグループへ戻るリンクを作成)

チャットメッセージページを作成します。

link_toメソッドでチャットグループへ戻れるようにリンクを作成しました。

メッセージ表示と投稿フォームを仮置きしています。

表示内容:

https://gyazo.com/2c24e1dc6141ad40b4a49f983628bda9

 

 

 

①②Carrierwaveを使用して、画像を保存できるようにする

app/models/chat_message.rb

class ChatMessage < ApplicationRecord
 belongs_to :user
 belongs_to :chat_group
 mount_uploader :image, ImageUploader
end

ユーザーアイコンやチャットグループアイコンの時に、Carrierwaveのgemはインストールして使えるようにしてあるので、modelに設定するところから始めます。

mount_uploaderでimageカラムを指定しています。

 

Carrierwaveについて

▶︎ https://qiita.com/nekotanku/items/5da43600f35eada64eac

 

 

 

①③コントローラー編集

投稿したフォームを保存できるようにcreateアクションとストロングパラメーターを作成し、処理内容をコードしていきます。

https://gyazo.com/7234c5d7d9159ba9693db1fd0bc9ef9d

createアクション

@coversations = ChatMessage.new(messages_params)でインスタンスを生成し、インスタンス変数(@conversations)へ代入。

 

ストロングパラメーターの内容

params.require(:chat_message).permit(:message, :image, :chat_group_id).merge(user_id: current_user.id)

 

params

送られてきたメッセージを受け取ります。

 

require(:chat_message)

送られてきた情報をモデルと紐付けます(今回はchat_messageモデルを使用してメッセージを保存します)。

 

permit(:message, :image, :chat_group_id)

permitで保存許可したい内容を記述します。

 

merge(user_id: current_user.id)

permitで許可されなかった情報を保存できるようにします。

 

ストロングパラメーターについて

▶︎ https://qiita.com/ozackiee/items/f100fd51f4839b3fdca8

 

 

 

①④font-awesome-railsをインストール、使用できるようにする

Font Awesomeで用意されているアイコンを使用したいのでfont-awesome-railsをインストールします。

gem 'font-awesome-rails'

$bundle install

app/assets/stylesheets/application.scss

@import "font-awesome";

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

 

font-awesome-railsについて

▶︎ https://pikawaka.com/rails/font_awesome_rails

 

🚨 font-awesome-railsは最新版font-awesome5には対応していないみたいです。

font-awesomeのversion5の一部のアイコンが表示されないので、対応させたい場合はfont-awesome-sassをインストールします。

gem 'font-awesome-sass'

$bundle install

app/assets/stylesheets/application.scss

@import 'font-awesome-sprockets';
@import 'font-awesome';

※絶対この順番にしてください。

入れ替えてしまうとアイコンが表示されなくなります。

$brew install yarn

※yarnをインストールをしていない場合はインストールします

 

 

brew

Homebrewのこと。

デフォルトでは利用できない便利なツールをインストールしたりアンインストールしたりを管理するツールのこと。

macOSのためにあるツールです。

 

Homebrewについて

▶︎ https://qiita.com/TAByasu/items/47c6cfbeeafad39eda07

 

yarn

Node.js(JavaScript)のパッケージマネージャのこと。

パッケージマネージャとは、コンピュータに何のソフトウェアがインストールされたかを記録し、新しいソフトウェアのインストール・新しいバージョンへのソフトウェアの更新・以前インストールしたソフトウェアの削除を容易に行えるようにするプログラム。

 

yarnについて

▶︎ https://www.sejuku.net/blog/72222#:~:text=Yarn%E3%81%AFNode.js(JavaScript,%E3%81%9C%E3%81%B2%E4%BD%BF%E3%81%A3%E3%81%A6%E3%81%BF%E3%81%A6%E3%81%8F%E3%81%A0%E3%81%95%E3%81%84%E3%80%82

パッケージマネージャについて

▶︎ https://www.debian.org/doc/manuals/aptitude/pr01s02.ja.html#:~:text=%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8%E3%83%9E%E3%83%8D%E3%83%BC%E3%82%B8%E3%83%A3%E3%81%A8%E3%81%AF%E3%80%81%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%82%BF,%E3%82%88%E3%81%86%E3%81%AB%E3%81%99%E3%82%8B%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%81%A7%E3%81%99%E3%80%82

 

font-awesome(version5)はフロントエンド開発との連携機能が更に強化されて、手軽にJavaScriptのバンドルにフォントを埋め込むことができるようになっています。

 

font-awesome(v5)について

▶︎ https://qiita.com/riversun/items/4faa56ac40071f638313

 

 

yarnをインストールしたら、サーバーを再起動($rails s)

これでfontawesome(v5)が使えるようになりました。

 

 

 

①⑤index.html.erbを編集(投稿フォームを作成、保存)

https://gyazo.com/00118a1f84903b61cc7e57270259d036

投稿フォームから画像とメッセージが保存できるか確かめます。

注意しなければならないのは、

・text_field_tagのchat_message[chat_group_id]

・file_fieldのname: 'chat_message[image]'

・text_areaのname: 'chat_message[message]'

です。

これがparamsとして送られると、

:chat_message => {:chat_group_id => "〇〇", :image => "〇〇", :message => "〇〇" }

とハッシュ構造されて送られます。

実際に保存できるか確かめます。

https://gyazo.com/87fc9036ca4d4723c6e8fe7b0354446c

画像とメッセージを投稿してみます。

これで保存できるようになりました。

 

 

 

 

今回の実装で苦労したのは、フォームから投稿する時にchat_group_idは保存できているのに、メッセージと画像がparamsとして送られているのに保存できずに時間がかかったことです😅

途中でname属性でハッシュさせたらどうだろうと気づくことができました。

name属性の使い方の勉強になりました。

 

次回はチャットメッセージの実装の続きを書こうと思っています。

 

 

 

 

 

 

 

 

 

 

 

 以上です。